func (c Checker) doChecks() (types.Attempts, []*tls.Conn) {
	checks := make(types.Attempts, c.Attempts)
	conns := make([]*tls.Conn, c.Attempts)
	for i := 0; i < c.Attempts; i++ {
		dialer := &net.Dialer{Timeout: c.Timeout}
		start := time.Now()
		conn, err := tls.DialWithDialer(dialer, "tcp", c.URL, c.tlsConfig)
		checks[i].RTT = time.Since(start)
		conns[i] = conn
		if err != nil {
			checks[i].Error = err.Error()
			continue
		}
	}
	return checks, conns
}
doChecks executes the checks and returns each attempt
along with its associated TLS connection. These connections
will be open, so it's vital that conclude() is called,
passing in the connections, so that they will be inspected
and closed properly.
package tls
import (
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"time"
	"github.com/sourcegraph/checkup/types"
)
const Type = "tls"
type Checker struct {
	Name string `json:"endpoint_name"`
	URL string `json:"endpoint_url"`
	Timeout time.Duration `json:"timeout,omitempty"`
	ThresholdRTT time.Duration `json:"threshold_rtt,omitempty"`
	Attempts int `json:"attempts,omitempty"`
	CertExpiryThreshold time.Duration `json:"cert_expiry_threshold,omitempty"`
	TrustedRoots []string `json:"trusted_roots,omitempty"`
	tlsConfig *tls.Config
}
func New(config json.RawMessage) (Checker, error) {
	var checker Checker
	err := json.Unmarshal(config, &checker)
	return checker, err
}
func (Checker) Type() string {
	return Type
}
func (c Checker) Check() (types.Result, error) {
	if c.Attempts < 1 {
		c.Attempts = 1
	}
	if c.CertExpiryThreshold == 0 {
		c.CertExpiryThreshold = 24 * time.Hour * 14
	}
	if len(c.TrustedRoots) > 0 {
		if c.tlsConfig == nil {
			c.tlsConfig = new(tls.Config)
		}
		if c.tlsConfig.RootCAs == nil {
			c.tlsConfig.RootCAs = x509.NewCertPool()
		}
		for _, fname := range c.TrustedRoots {
			pemData, err := ioutil.ReadFile(fname)
			if err != nil {
				return types.Result{}, fmt.Errorf("error loading file: %w", err)
			}
			if !c.tlsConfig.RootCAs.AppendCertsFromPEM(pemData) {
				return types.Result{}, fmt.Errorf("error appending certs from PEM %s: %w", fname, err)
			}
		}
	}
	attempts, conns := c.doChecks()
	result := types.NewResult()
	result.Title = c.Name
	result.Endpoint = c.URL
	result.Times = attempts
	result.ThresholdRTT = c.ThresholdRTT
	return c.conclude(conns, result), nil
}