func NewTLSClient(ctx context.Context, serverAddress string, serverName string, cert string, privateKey string, certificateAuthority string) (*Client, error) {
	var opts []grpc.DialOption
	if len(cert) == 0 || len(privateKey) == 0 || len(certificateAuthority) == 0 || len(serverName) == 0 {
		return nil, errors.New("Insufficient security credentials provided")
	}
	certificate, err := tls.LoadX509KeyPair(cert, privateKey)
	if err != nil {
		return nil, fmt.Errorf("Could not load client key pair: %s", err)
	}
	certPool := x509.NewCertPool()
	ca, err := ioutil.ReadFile(certificateAuthority)
	if err != nil {
		return nil, fmt.Errorf("Could not read ca certificate: %s", err)
	}
	if ok := certPool.AppendCertsFromPEM(ca); !ok {
		return nil, errors.New("Failed to append ca certs")
	}
	creds := credentials.NewTLS(&tls.Config{
		ServerName:   serverName,
		Certificates: []tls.Certificate{certificate},
		RootCAs:      certPool,
	})
	opts = append(opts, grpc.WithTransportCredentials(creds))
	return NewClient(ctx, serverAddress, opts)
}
NewTLSClient returns a new Stela gRPC client for the given server address.  You must provide paths to a
certificate authority, client certificate, and client private key.  You must also provide a value for
server name that matches the common name in the certificate of the server you are connecting to.
The client's Close method should be called when the returned client is no longer needed.
package api
import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"sync"
	"github.com/forestgiant/netutil"
	"github.com/forestgiant/stela"
	"github.com/forestgiant/stela/pb"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/grpclog"
	fggrpclog "github.com/forestgiant/grpclog"
)
func init() {
	grpclog.SetLogger(&fggrpclog.Suppressed{})
}
type Client struct {
	stela.Client
	mu sync.RWMutex
	rpc       pb.StelaClient
	conn      *grpc.ClientConn
	Hostname  string
	callbacks map[string]func(s *stela.Service)
}
func NewClient(ctx context.Context, stelaAddress string, opts []grpc.DialOption) (*Client, error) {
	c := &Client{}
	host, err := os.Hostname()
	if err != nil {
		return nil, err
	}
	c.Hostname = host
	c.Address = netutil.LocalIPv4().String()
	if len(opts) == 0 {
		opts = append(opts, grpc.WithInsecure())
	}
	opts = append(opts, grpc.FailOnNonTempDialError(true))
	opts = append(opts, grpc.WithBlock())
	c.conn, err = grpc.DialContext(ctx, stelaAddress, opts...)
	if err != nil {
		return nil, err
	}
	c.rpc = pb.NewStelaClient(c.conn)
	resp, err := c.rpc.AddClient(ctx, &pb.AddClientRequest{ClientAddress: c.Address})
	if err != nil {
		return nil, err
	}
	c.ID = resp.ClientId
	if err := c.connect(); err != nil {
		return nil, err
	}
	return c, nil
}