github.com/true-sqn/fabric@v2.1.1+incompatible/internal/peer/common/peerclient.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package common
     8  
     9  import (
    10  	"context"
    11  	"crypto/tls"
    12  	"io/ioutil"
    13  	"time"
    14  
    15  	pb "github.com/hyperledger/fabric-protos-go/peer"
    16  	"github.com/hyperledger/fabric/core/config"
    17  	"github.com/hyperledger/fabric/internal/pkg/comm"
    18  	"github.com/pkg/errors"
    19  	"github.com/spf13/viper"
    20  )
    21  
    22  // PeerClient represents a client for communicating with a peer
    23  type PeerClient struct {
    24  	CommonClient
    25  }
    26  
    27  // NewPeerClientFromEnv creates an instance of a PeerClient from the global
    28  // Viper instance
    29  func NewPeerClientFromEnv() (*PeerClient, error) {
    30  	address, override, clientConfig, err := configFromEnv("peer")
    31  	if err != nil {
    32  		return nil, errors.WithMessage(err, "failed to load config for PeerClient")
    33  	}
    34  	return newPeerClientForClientConfig(address, override, clientConfig)
    35  }
    36  
    37  // NewPeerClientForAddress creates an instance of a PeerClient using the
    38  // provided peer address and, if TLS is enabled, the TLS root cert file
    39  func NewPeerClientForAddress(address, tlsRootCertFile string) (*PeerClient, error) {
    40  	if address == "" {
    41  		return nil, errors.New("peer address must be set")
    42  	}
    43  
    44  	override := viper.GetString("peer.tls.serverhostoverride")
    45  	clientConfig := comm.ClientConfig{}
    46  	clientConfig.Timeout = viper.GetDuration("peer.client.connTimeout")
    47  	if clientConfig.Timeout == time.Duration(0) {
    48  		clientConfig.Timeout = defaultConnTimeout
    49  	}
    50  
    51  	secOpts := comm.SecureOptions{
    52  		UseTLS:            viper.GetBool("peer.tls.enabled"),
    53  		RequireClientCert: viper.GetBool("peer.tls.clientAuthRequired"),
    54  	}
    55  
    56  	if secOpts.RequireClientCert {
    57  		keyPEM, err := ioutil.ReadFile(config.GetPath("peer.tls.clientKey.file"))
    58  		if err != nil {
    59  			return nil, errors.WithMessage(err, "unable to load peer.tls.clientKey.file")
    60  		}
    61  		secOpts.Key = keyPEM
    62  		certPEM, err := ioutil.ReadFile(config.GetPath("peer.tls.clientCert.file"))
    63  		if err != nil {
    64  			return nil, errors.WithMessage(err, "unable to load peer.tls.clientCert.file")
    65  		}
    66  		secOpts.Certificate = certPEM
    67  	}
    68  	clientConfig.SecOpts = secOpts
    69  
    70  	if clientConfig.SecOpts.UseTLS {
    71  		if tlsRootCertFile == "" {
    72  			return nil, errors.New("tls root cert file must be set")
    73  		}
    74  		caPEM, res := ioutil.ReadFile(tlsRootCertFile)
    75  		if res != nil {
    76  			return nil, errors.WithMessagef(res, "unable to load TLS root cert file from %s", tlsRootCertFile)
    77  		}
    78  		clientConfig.SecOpts.ServerRootCAs = [][]byte{caPEM}
    79  	}
    80  	return newPeerClientForClientConfig(address, override, clientConfig)
    81  }
    82  
    83  func newPeerClientForClientConfig(address, override string, clientConfig comm.ClientConfig) (*PeerClient, error) {
    84  	// set the default keepalive options to match the server
    85  	clientConfig.KaOpts = comm.DefaultKeepaliveOptions
    86  	gClient, err := comm.NewGRPCClient(clientConfig)
    87  	if err != nil {
    88  		return nil, errors.WithMessage(err, "failed to create PeerClient from config")
    89  	}
    90  	pClient := &PeerClient{
    91  		CommonClient: CommonClient{
    92  			GRPCClient: gClient,
    93  			Address:    address,
    94  			sn:         override}}
    95  	return pClient, nil
    96  }
    97  
    98  // Endorser returns a client for the Endorser service
    99  func (pc *PeerClient) Endorser() (pb.EndorserClient, error) {
   100  	conn, err := pc.CommonClient.NewConnection(pc.Address, comm.ServerNameOverride(pc.sn))
   101  	if err != nil {
   102  		return nil, errors.WithMessagef(err, "endorser client failed to connect to %s", pc.Address)
   103  	}
   104  	return pb.NewEndorserClient(conn), nil
   105  }
   106  
   107  // Deliver returns a client for the Deliver service
   108  func (pc *PeerClient) Deliver() (pb.Deliver_DeliverClient, error) {
   109  	conn, err := pc.CommonClient.NewConnection(pc.Address, comm.ServerNameOverride(pc.sn))
   110  	if err != nil {
   111  		return nil, errors.WithMessagef(err, "deliver client failed to connect to %s", pc.Address)
   112  	}
   113  	return pb.NewDeliverClient(conn).Deliver(context.TODO())
   114  }
   115  
   116  // PeerDeliver returns a client for the Deliver service for peer-specific use
   117  // cases (i.e. DeliverFiltered)
   118  func (pc *PeerClient) PeerDeliver() (pb.DeliverClient, error) {
   119  	conn, err := pc.CommonClient.NewConnection(pc.Address, comm.ServerNameOverride(pc.sn))
   120  	if err != nil {
   121  		return nil, errors.WithMessagef(err, "deliver client failed to connect to %s", pc.Address)
   122  	}
   123  	return pb.NewDeliverClient(conn), nil
   124  }
   125  
   126  // Certificate returns the TLS client certificate (if available)
   127  func (pc *PeerClient) Certificate() tls.Certificate {
   128  	return pc.CommonClient.Certificate()
   129  }
   130  
   131  // GetEndorserClient returns a new endorser client. If the both the address and
   132  // tlsRootCertFile are not provided, the target values for the client are taken
   133  // from the configuration settings for "peer.address" and
   134  // "peer.tls.rootcert.file"
   135  func GetEndorserClient(address, tlsRootCertFile string) (pb.EndorserClient, error) {
   136  	var peerClient *PeerClient
   137  	var err error
   138  	if address != "" {
   139  		peerClient, err = NewPeerClientForAddress(address, tlsRootCertFile)
   140  	} else {
   141  		peerClient, err = NewPeerClientFromEnv()
   142  	}
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	return peerClient.Endorser()
   147  }
   148  
   149  // GetCertificate returns the client's TLS certificate
   150  func GetCertificate() (tls.Certificate, error) {
   151  	peerClient, err := NewPeerClientFromEnv()
   152  	if err != nil {
   153  		return tls.Certificate{}, err
   154  	}
   155  	return peerClient.Certificate(), nil
   156  }
   157  
   158  // GetDeliverClient returns a new deliver client. If both the address and
   159  // tlsRootCertFile are not provided, the target values for the client are taken
   160  // from the configuration settings for "peer.address" and
   161  // "peer.tls.rootcert.file"
   162  func GetDeliverClient(address, tlsRootCertFile string) (pb.Deliver_DeliverClient, error) {
   163  	var peerClient *PeerClient
   164  	var err error
   165  	if address != "" {
   166  		peerClient, err = NewPeerClientForAddress(address, tlsRootCertFile)
   167  	} else {
   168  		peerClient, err = NewPeerClientFromEnv()
   169  	}
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  	return peerClient.Deliver()
   174  }
   175  
   176  // GetPeerDeliverClient returns a new deliver client. If both the address and
   177  // tlsRootCertFile are not provided, the target values for the client are taken
   178  // from the configuration settings for "peer.address" and
   179  // "peer.tls.rootcert.file"
   180  func GetPeerDeliverClient(address, tlsRootCertFile string) (pb.DeliverClient, error) {
   181  	var peerClient *PeerClient
   182  	var err error
   183  	if address != "" {
   184  		peerClient, err = NewPeerClientForAddress(address, tlsRootCertFile)
   185  	} else {
   186  		peerClient, err = NewPeerClientFromEnv()
   187  	}
   188  	if err != nil {
   189  		return nil, err
   190  	}
   191  	return peerClient.PeerDeliver()
   192  }