github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/gossip/comm/comm_impl.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package comm
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/tls"
    12  	"errors"
    13  	"fmt"
    14  	"net"
    15  	"reflect"
    16  	"sync"
    17  	"sync/atomic"
    18  	"time"
    19  
    20  	"github.com/hyperledger/fabric/gossip/api"
    21  	"github.com/hyperledger/fabric/gossip/common"
    22  	"github.com/hyperledger/fabric/gossip/identity"
    23  	"github.com/hyperledger/fabric/gossip/util"
    24  	proto "github.com/hyperledger/fabric/protos/gossip"
    25  	"github.com/op/go-logging"
    26  	"github.com/spf13/viper"
    27  	"golang.org/x/net/context"
    28  	"google.golang.org/grpc"
    29  	"google.golang.org/grpc/credentials"
    30  	"google.golang.org/grpc/peer"
    31  )
    32  
    33  const (
    34  	defDialTimeout  = time.Second * time.Duration(3)
    35  	defConnTimeout  = time.Second * time.Duration(2)
    36  	defRecvBuffSize = 20
    37  	defSendBuffSize = 20
    38  )
    39  
    40  // SetDialTimeout sets the dial timeout
    41  func SetDialTimeout(timeout time.Duration) {
    42  	viper.Set("peer.gossip.dialTimeout", timeout)
    43  }
    44  
    45  func (c *commImpl) SetDialOpts(opts ...grpc.DialOption) {
    46  	if len(opts) == 0 {
    47  		c.logger.Warning("Given an empty set of grpc.DialOption, aborting")
    48  		return
    49  	}
    50  	c.opts = opts
    51  }
    52  
    53  // NewCommInstanceWithServer creates a comm instance that creates an underlying gRPC server
    54  func NewCommInstanceWithServer(port int, idMapper identity.Mapper, peerIdentity api.PeerIdentityType,
    55  	secureDialOpts api.PeerSecureDialOpts, dialOpts ...grpc.DialOption) (Comm, error) {
    56  
    57  	var ll net.Listener
    58  	var s *grpc.Server
    59  	var certHash []byte
    60  
    61  	if len(dialOpts) == 0 {
    62  		dialOpts = []grpc.DialOption{grpc.WithTimeout(util.GetDurationOrDefault("peer.gossip.dialTimeout", defDialTimeout))}
    63  	}
    64  
    65  	if port > 0 {
    66  		s, ll, secureDialOpts, certHash = createGRPCLayer(port)
    67  	}
    68  
    69  	commInst := &commImpl{
    70  		selfCertHash:   certHash,
    71  		PKIID:          idMapper.GetPKIidOfCert(peerIdentity),
    72  		idMapper:       idMapper,
    73  		logger:         util.GetLogger(util.LoggingCommModule, fmt.Sprintf("%d", port)),
    74  		peerIdentity:   peerIdentity,
    75  		opts:           dialOpts,
    76  		secureDialOpts: secureDialOpts,
    77  		port:           port,
    78  		lsnr:           ll,
    79  		gSrv:           s,
    80  		msgPublisher:   NewChannelDemultiplexer(),
    81  		lock:           &sync.RWMutex{},
    82  		deadEndpoints:  make(chan common.PKIidType, 100),
    83  		stopping:       int32(0),
    84  		exitChan:       make(chan struct{}, 1),
    85  		subscriptions:  make([]chan proto.ReceivedMessage, 0),
    86  	}
    87  	commInst.connStore = newConnStore(commInst, commInst.logger)
    88  
    89  	if port > 0 {
    90  		commInst.stopWG.Add(1)
    91  		go func() {
    92  			defer commInst.stopWG.Done()
    93  			s.Serve(ll)
    94  		}()
    95  		proto.RegisterGossipServer(s, commInst)
    96  	}
    97  
    98  	return commInst, nil
    99  }
   100  
   101  // NewCommInstance creates a new comm instance that binds itself to the given gRPC server
   102  func NewCommInstance(s *grpc.Server, cert *tls.Certificate, idStore identity.Mapper,
   103  	peerIdentity api.PeerIdentityType, secureDialOpts api.PeerSecureDialOpts,
   104  	dialOpts ...grpc.DialOption) (Comm, error) {
   105  
   106  	dialOpts = append(dialOpts, grpc.WithTimeout(util.GetDurationOrDefault("peer.gossip.dialTimeout", defDialTimeout)))
   107  	commInst, err := NewCommInstanceWithServer(-1, idStore, peerIdentity, secureDialOpts, dialOpts...)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	if cert != nil {
   113  		inst := commInst.(*commImpl)
   114  		if len(cert.Certificate) == 0 {
   115  			inst.logger.Panic("Certificate supplied but certificate chain is empty")
   116  		} else {
   117  			inst.selfCertHash = certHashFromRawCert(cert.Certificate[0])
   118  		}
   119  	}
   120  
   121  	proto.RegisterGossipServer(s, commInst.(*commImpl))
   122  
   123  	return commInst, nil
   124  }
   125  
   126  type commImpl struct {
   127  	selfCertHash   []byte
   128  	peerIdentity   api.PeerIdentityType
   129  	idMapper       identity.Mapper
   130  	logger         *logging.Logger
   131  	opts           []grpc.DialOption
   132  	secureDialOpts func() []grpc.DialOption
   133  	connStore      *connectionStore
   134  	PKIID          []byte
   135  	deadEndpoints  chan common.PKIidType
   136  	msgPublisher   *ChannelDeMultiplexer
   137  	lock           *sync.RWMutex
   138  	lsnr           net.Listener
   139  	gSrv           *grpc.Server
   140  	exitChan       chan struct{}
   141  	stopWG         sync.WaitGroup
   142  	subscriptions  []chan proto.ReceivedMessage
   143  	port           int
   144  	stopping       int32
   145  }
   146  
   147  func (c *commImpl) createConnection(endpoint string, expectedPKIID common.PKIidType) (*connection, error) {
   148  	var err error
   149  	var cc *grpc.ClientConn
   150  	var stream proto.Gossip_GossipStreamClient
   151  	var pkiID common.PKIidType
   152  	var connInfo *proto.ConnectionInfo
   153  	var dialOpts []grpc.DialOption
   154  
   155  	c.logger.Debug("Entering", endpoint, expectedPKIID)
   156  	defer c.logger.Debug("Exiting")
   157  
   158  	if c.isStopping() {
   159  		return nil, errors.New("Stopping")
   160  	}
   161  	dialOpts = append(dialOpts, c.secureDialOpts()...)
   162  	dialOpts = append(dialOpts, grpc.WithBlock())
   163  	dialOpts = append(dialOpts, c.opts...)
   164  	cc, err = grpc.Dial(endpoint, dialOpts...)
   165  	if err != nil {
   166  		return nil, err
   167  	}
   168  
   169  	cl := proto.NewGossipClient(cc)
   170  
   171  	ctx, cancel := context.WithTimeout(context.Background(), defConnTimeout)
   172  	defer cancel()
   173  	if _, err = cl.Ping(ctx, &proto.Empty{}); err != nil {
   174  		cc.Close()
   175  		return nil, err
   176  	}
   177  
   178  	ctx, cf := context.WithCancel(context.Background())
   179  	if stream, err = cl.GossipStream(ctx); err == nil {
   180  		connInfo, err = c.authenticateRemotePeer(stream)
   181  		if err == nil {
   182  			pkiID = connInfo.ID
   183  			if expectedPKIID != nil && !bytes.Equal(pkiID, expectedPKIID) {
   184  				// PKIID is nil when we don't know the remote PKI id's
   185  				c.logger.Warning("Remote endpoint claims to be a different peer, expected", expectedPKIID, "but got", pkiID)
   186  				cc.Close()
   187  				return nil, errors.New("Authentication failure")
   188  			}
   189  			conn := newConnection(cl, cc, stream, nil)
   190  			conn.pkiID = pkiID
   191  			conn.info = connInfo
   192  			conn.logger = c.logger
   193  			conn.cancel = cf
   194  
   195  			h := func(m *proto.SignedGossipMessage) {
   196  				c.logger.Debug("Got message:", m)
   197  				c.msgPublisher.DeMultiplex(&ReceivedMessageImpl{
   198  					conn:                conn,
   199  					lock:                conn,
   200  					SignedGossipMessage: m,
   201  					connInfo:            connInfo,
   202  				})
   203  			}
   204  			conn.handler = h
   205  			return conn, nil
   206  		}
   207  		c.logger.Warning("Authentication failed:", err)
   208  	}
   209  	cc.Close()
   210  	return nil, err
   211  }
   212  
   213  func (c *commImpl) Send(msg *proto.SignedGossipMessage, peers ...*RemotePeer) {
   214  	if c.isStopping() || len(peers) == 0 {
   215  		return
   216  	}
   217  
   218  	c.logger.Debug("Entering, sending", msg, "to ", len(peers), "peers")
   219  
   220  	for _, peer := range peers {
   221  		go func(peer *RemotePeer, msg *proto.SignedGossipMessage) {
   222  			c.sendToEndpoint(peer, msg)
   223  		}(peer, msg)
   224  	}
   225  }
   226  
   227  func (c *commImpl) sendToEndpoint(peer *RemotePeer, msg *proto.SignedGossipMessage) {
   228  	if c.isStopping() {
   229  		return
   230  	}
   231  	c.logger.Debug("Entering, Sending to", peer.Endpoint, ", msg:", msg)
   232  	defer c.logger.Debug("Exiting")
   233  	var err error
   234  
   235  	conn, err := c.connStore.getConnection(peer)
   236  	if err == nil {
   237  		disConnectOnErr := func(err error) {
   238  			c.logger.Warning(peer, "isn't responsive:", err)
   239  			c.disconnect(peer.PKIID)
   240  		}
   241  		conn.send(msg, disConnectOnErr)
   242  		return
   243  	}
   244  	c.logger.Warning("Failed obtaining connection for", peer, "reason:", err)
   245  	c.disconnect(peer.PKIID)
   246  }
   247  
   248  func (c *commImpl) isStopping() bool {
   249  	return atomic.LoadInt32(&c.stopping) == int32(1)
   250  }
   251  
   252  func (c *commImpl) Probe(remotePeer *RemotePeer) error {
   253  	var dialOpts []grpc.DialOption
   254  	endpoint := remotePeer.Endpoint
   255  	pkiID := remotePeer.PKIID
   256  	if c.isStopping() {
   257  		return errors.New("Stopping")
   258  	}
   259  	c.logger.Debug("Entering, endpoint:", endpoint, "PKIID:", pkiID)
   260  	dialOpts = append(dialOpts, c.secureDialOpts()...)
   261  	dialOpts = append(dialOpts, grpc.WithBlock())
   262  	dialOpts = append(dialOpts, c.opts...)
   263  
   264  	cc, err := grpc.Dial(remotePeer.Endpoint, dialOpts...)
   265  	if err != nil {
   266  		c.logger.Debug("Returning", err)
   267  		return err
   268  	}
   269  	defer cc.Close()
   270  	cl := proto.NewGossipClient(cc)
   271  	ctx, cancel := context.WithTimeout(context.Background(), defConnTimeout)
   272  	defer cancel()
   273  	_, err = cl.Ping(ctx, &proto.Empty{})
   274  	c.logger.Debug("Returning", err)
   275  	return err
   276  }
   277  
   278  func (c *commImpl) Handshake(remotePeer *RemotePeer) (api.PeerIdentityType, error) {
   279  	var dialOpts []grpc.DialOption
   280  	dialOpts = append(dialOpts, c.secureDialOpts()...)
   281  	dialOpts = append(dialOpts, grpc.WithBlock())
   282  	dialOpts = append(dialOpts, c.opts...)
   283  
   284  	cc, err := grpc.Dial(remotePeer.Endpoint, dialOpts...)
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  	defer cc.Close()
   289  
   290  	cl := proto.NewGossipClient(cc)
   291  	ctx, cancel := context.WithTimeout(context.Background(), defConnTimeout)
   292  	defer cancel()
   293  	if _, err = cl.Ping(ctx, &proto.Empty{}); err != nil {
   294  		return nil, err
   295  	}
   296  
   297  	stream, err := cl.GossipStream(context.Background())
   298  	if err != nil {
   299  		return nil, err
   300  	}
   301  	connInfo, err := c.authenticateRemotePeer(stream)
   302  	if err != nil {
   303  		c.logger.Warning("Authentication failed:", err)
   304  		return nil, err
   305  	}
   306  	if len(remotePeer.PKIID) > 0 && !bytes.Equal(connInfo.ID, remotePeer.PKIID) {
   307  		return nil, errors.New("PKI-ID of remote peer doesn't match expected PKI-ID")
   308  	}
   309  	return connInfo.Identity, nil
   310  }
   311  
   312  func (c *commImpl) Accept(acceptor common.MessageAcceptor) <-chan proto.ReceivedMessage {
   313  	genericChan := c.msgPublisher.AddChannel(acceptor)
   314  	specificChan := make(chan proto.ReceivedMessage, 10)
   315  
   316  	if c.isStopping() {
   317  		c.logger.Warning("Accept() called but comm module is stopping, returning empty channel")
   318  		return specificChan
   319  	}
   320  
   321  	c.lock.Lock()
   322  	c.subscriptions = append(c.subscriptions, specificChan)
   323  	c.lock.Unlock()
   324  
   325  	go func() {
   326  		defer c.logger.Debug("Exiting Accept() loop")
   327  		defer func() {
   328  			recover()
   329  		}()
   330  
   331  		c.stopWG.Add(1)
   332  		defer c.stopWG.Done()
   333  
   334  		for {
   335  			select {
   336  			case msg := <-genericChan:
   337  				specificChan <- msg.(*ReceivedMessageImpl)
   338  			case s := <-c.exitChan:
   339  				c.exitChan <- s
   340  				return
   341  			}
   342  		}
   343  	}()
   344  	return specificChan
   345  }
   346  
   347  func (c *commImpl) PresumedDead() <-chan common.PKIidType {
   348  	return c.deadEndpoints
   349  }
   350  
   351  func (c *commImpl) CloseConn(peer *RemotePeer) {
   352  	c.logger.Debug("Closing connection for", peer)
   353  	c.connStore.closeConn(peer)
   354  }
   355  
   356  func (c *commImpl) emptySubscriptions() {
   357  	c.lock.Lock()
   358  	defer c.lock.Unlock()
   359  	for _, ch := range c.subscriptions {
   360  		close(ch)
   361  	}
   362  }
   363  
   364  func (c *commImpl) Stop() {
   365  	if c.isStopping() {
   366  		return
   367  	}
   368  	atomic.StoreInt32(&c.stopping, int32(1))
   369  	c.logger.Info("Stopping")
   370  	defer c.logger.Info("Stopped")
   371  	if c.gSrv != nil {
   372  		c.gSrv.Stop()
   373  	}
   374  	if c.lsnr != nil {
   375  		c.lsnr.Close()
   376  	}
   377  	c.connStore.shutdown()
   378  	c.logger.Debug("Shut down connection store, connection count:", c.connStore.connNum())
   379  	c.exitChan <- struct{}{}
   380  	c.msgPublisher.Close()
   381  	c.logger.Debug("Shut down publisher")
   382  	c.emptySubscriptions()
   383  	c.logger.Debug("Closed subscriptions, waiting for goroutines to stop...")
   384  	c.stopWG.Wait()
   385  }
   386  
   387  func (c *commImpl) GetPKIid() common.PKIidType {
   388  	return c.PKIID
   389  }
   390  
   391  func extractRemoteAddress(stream stream) string {
   392  	var remoteAddress string
   393  	p, ok := peer.FromContext(stream.Context())
   394  	if ok {
   395  		if address := p.Addr; address != nil {
   396  			remoteAddress = address.String()
   397  		}
   398  	}
   399  	return remoteAddress
   400  }
   401  
   402  func (c *commImpl) authenticateRemotePeer(stream stream) (*proto.ConnectionInfo, error) {
   403  	ctx := stream.Context()
   404  	remoteAddress := extractRemoteAddress(stream)
   405  	remoteCertHash := extractCertificateHashFromContext(ctx)
   406  	var err error
   407  	var cMsg *proto.SignedGossipMessage
   408  	var signer proto.Signer
   409  	useTLS := c.selfCertHash != nil
   410  
   411  	// If TLS is enabled, sign the connection message in order to bind
   412  	// the TLS session to the peer's identity
   413  	if useTLS {
   414  		signer = func(msg []byte) ([]byte, error) {
   415  			return c.idMapper.Sign(msg)
   416  		}
   417  	} else { // If we don't use TLS, we have no unique text to sign,
   418  		//  so don't sign anything
   419  		signer = func(msg []byte) ([]byte, error) {
   420  			return msg, nil
   421  		}
   422  	}
   423  
   424  	// TLS enabled but not detected on other side
   425  	if useTLS && len(remoteCertHash) == 0 {
   426  		c.logger.Warningf("%s didn't send TLS certificate", remoteAddress)
   427  		return nil, errors.New("No TLS certificate")
   428  	}
   429  
   430  	cMsg, err = c.createConnectionMsg(c.PKIID, c.selfCertHash, c.peerIdentity, signer)
   431  	if err != nil {
   432  		return nil, err
   433  	}
   434  
   435  	c.logger.Debug("Sending", cMsg, "to", remoteAddress)
   436  	stream.Send(cMsg.Envelope)
   437  	m, err := readWithTimeout(stream, util.GetDurationOrDefault("peer.gossip.connTimeout", defConnTimeout), remoteAddress)
   438  	if err != nil {
   439  		c.logger.Warningf("Failed reading messge from %s, reason: %v", remoteAddress, err)
   440  		return nil, err
   441  	}
   442  	receivedMsg := m.GetConn()
   443  	if receivedMsg == nil {
   444  		c.logger.Warning("Expected connection message from", remoteAddress, "but got", receivedMsg)
   445  		return nil, errors.New("Wrong type")
   446  	}
   447  
   448  	if receivedMsg.PkiId == nil {
   449  		c.logger.Warning("%s didn't send a pkiID", remoteAddress)
   450  		return nil, errors.New("No PKI-ID")
   451  	}
   452  
   453  	c.logger.Debug("Received", receivedMsg, "from", remoteAddress)
   454  	err = c.idMapper.Put(receivedMsg.PkiId, receivedMsg.Identity)
   455  	if err != nil {
   456  		c.logger.Warning("Identity store rejected", remoteAddress, ":", err)
   457  		return nil, err
   458  	}
   459  
   460  	connInfo := &proto.ConnectionInfo{
   461  		ID:       receivedMsg.PkiId,
   462  		Identity: receivedMsg.Identity,
   463  		Endpoint: remoteAddress,
   464  	}
   465  
   466  	// if TLS is enabled and detected, verify remote peer
   467  	if useTLS {
   468  		// If the remote peer sent its TLS certificate, make sure it actually matches the TLS cert
   469  		// that the peer used.
   470  		if !bytes.Equal(remoteCertHash, receivedMsg.TlsCertHash) {
   471  			return nil, fmt.Errorf("Expected %v in remote hash of TLS cert, but got %v", remoteCertHash, receivedMsg.TlsCertHash)
   472  		}
   473  		verifier := func(peerIdentity []byte, signature, message []byte) error {
   474  			pkiID := c.idMapper.GetPKIidOfCert(api.PeerIdentityType(peerIdentity))
   475  			return c.idMapper.Verify(pkiID, signature, message)
   476  		}
   477  		err = m.Verify(receivedMsg.Identity, verifier)
   478  		if err != nil {
   479  			c.logger.Error("Failed verifying signature from", remoteAddress, ":", err)
   480  			return nil, err
   481  		}
   482  		connInfo.Auth = &proto.AuthInfo{
   483  			Signature:  m.Signature,
   484  			SignedData: m.Payload,
   485  		}
   486  	}
   487  
   488  	c.logger.Debug("Authenticated", remoteAddress)
   489  
   490  	return connInfo, nil
   491  }
   492  
   493  func (c *commImpl) GossipStream(stream proto.Gossip_GossipStreamServer) error {
   494  	if c.isStopping() {
   495  		return errors.New("Shutting down")
   496  	}
   497  	connInfo, err := c.authenticateRemotePeer(stream)
   498  	if err != nil {
   499  		c.logger.Error("Authentication failed:", err)
   500  		return err
   501  	}
   502  	c.logger.Debug("Servicing", extractRemoteAddress(stream))
   503  
   504  	conn := c.connStore.onConnected(stream, connInfo)
   505  
   506  	// if connStore denied the connection, it means we already have a connection to that peer
   507  	// so close this stream
   508  	if conn == nil {
   509  		return nil
   510  	}
   511  
   512  	h := func(m *proto.SignedGossipMessage) {
   513  		c.msgPublisher.DeMultiplex(&ReceivedMessageImpl{
   514  			conn:                conn,
   515  			lock:                conn,
   516  			SignedGossipMessage: m,
   517  			connInfo:            connInfo,
   518  		})
   519  	}
   520  
   521  	conn.handler = h
   522  
   523  	defer func() {
   524  		c.logger.Debug("Client", extractRemoteAddress(stream), " disconnected")
   525  		c.connStore.closeByPKIid(connInfo.ID)
   526  		conn.close()
   527  	}()
   528  
   529  	return conn.serviceConnection()
   530  }
   531  
   532  func (c *commImpl) Ping(context.Context, *proto.Empty) (*proto.Empty, error) {
   533  	return &proto.Empty{}, nil
   534  }
   535  
   536  func (c *commImpl) disconnect(pkiID common.PKIidType) {
   537  	if c.isStopping() {
   538  		return
   539  	}
   540  	c.deadEndpoints <- pkiID
   541  	c.connStore.closeByPKIid(pkiID)
   542  }
   543  
   544  func readWithTimeout(stream interface{}, timeout time.Duration, address string) (*proto.SignedGossipMessage, error) {
   545  	incChan := make(chan *proto.SignedGossipMessage, 1)
   546  	errChan := make(chan error, 1)
   547  	go func() {
   548  		if srvStr, isServerStr := stream.(proto.Gossip_GossipStreamServer); isServerStr {
   549  			if m, err := srvStr.Recv(); err == nil {
   550  				msg, err := m.ToGossipMessage()
   551  				if err != nil {
   552  					errChan <- err
   553  					return
   554  				}
   555  				incChan <- msg
   556  			}
   557  		} else if clStr, isClientStr := stream.(proto.Gossip_GossipStreamClient); isClientStr {
   558  			if m, err := clStr.Recv(); err == nil {
   559  				msg, err := m.ToGossipMessage()
   560  				if err != nil {
   561  					errChan <- err
   562  					return
   563  				}
   564  				incChan <- msg
   565  			}
   566  		} else {
   567  			panic(fmt.Errorf("Stream isn't a GossipStreamServer or a GossipStreamClient, but %v. Aborting", reflect.TypeOf(stream)))
   568  		}
   569  	}()
   570  	select {
   571  	case <-time.NewTicker(timeout).C:
   572  		return nil, fmt.Errorf("Timed out waiting for connection message from %s", address)
   573  	case m := <-incChan:
   574  		return m, nil
   575  	case err := <-errChan:
   576  		return nil, err
   577  	}
   578  }
   579  
   580  func (c *commImpl) createConnectionMsg(pkiID common.PKIidType, certHash []byte, cert api.PeerIdentityType, signer proto.Signer) (*proto.SignedGossipMessage, error) {
   581  	m := &proto.GossipMessage{
   582  		Tag:   proto.GossipMessage_EMPTY,
   583  		Nonce: 0,
   584  		Content: &proto.GossipMessage_Conn{
   585  			Conn: &proto.ConnEstablish{
   586  				TlsCertHash: certHash,
   587  				Identity:    cert,
   588  				PkiId:       pkiID,
   589  			},
   590  		},
   591  	}
   592  	sMsg := &proto.SignedGossipMessage{
   593  		GossipMessage: m,
   594  	}
   595  	_, err := sMsg.Sign(signer)
   596  	return sMsg, err
   597  }
   598  
   599  type stream interface {
   600  	Send(envelope *proto.Envelope) error
   601  	Recv() (*proto.Envelope, error)
   602  	grpc.Stream
   603  }
   604  
   605  func createGRPCLayer(port int) (*grpc.Server, net.Listener, api.PeerSecureDialOpts, []byte) {
   606  	var returnedCertHash []byte
   607  	var s *grpc.Server
   608  	var ll net.Listener
   609  	var err error
   610  	var serverOpts []grpc.ServerOption
   611  	var dialOpts []grpc.DialOption
   612  
   613  	cert := GenerateCertificatesOrPanic()
   614  	returnedCertHash = certHashFromRawCert(cert.Certificate[0])
   615  
   616  	tlsConf := &tls.Config{
   617  		Certificates:       []tls.Certificate{cert},
   618  		ClientAuth:         tls.RequestClientCert,
   619  		InsecureSkipVerify: true,
   620  	}
   621  	serverOpts = append(serverOpts, grpc.Creds(credentials.NewTLS(tlsConf)))
   622  	ta := credentials.NewTLS(&tls.Config{
   623  		Certificates:       []tls.Certificate{cert},
   624  		InsecureSkipVerify: true,
   625  	})
   626  	dialOpts = append(dialOpts, grpc.WithTransportCredentials(ta))
   627  
   628  	listenAddress := fmt.Sprintf("%s:%d", "", port)
   629  	ll, err = net.Listen("tcp", listenAddress)
   630  	if err != nil {
   631  		panic(err)
   632  	}
   633  	secureDialOpts := func() []grpc.DialOption {
   634  		return dialOpts
   635  	}
   636  	s = grpc.NewServer(serverOpts...)
   637  	return s, ll, secureDialOpts, returnedCertHash
   638  }