github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/peer/common/peerclient.go (about)

     1  /*
     2  Copyright hechain. 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  	"github.com/hechain20/hechain/internal/pkg/comm"
    16  	pb "github.com/hyperledger/fabric-protos-go/peer"
    17  	"github.com/pkg/errors"
    18  	"github.com/spf13/viper"
    19  )
    20  
    21  // PeerClient represents a client for communicating with a peer
    22  type PeerClient struct {
    23  	*CommonClient
    24  }
    25  
    26  // NewPeerClientFromEnv creates an instance of a PeerClient from the global
    27  // Viper instance
    28  func NewPeerClientFromEnv() (*PeerClient, error) {
    29  	address, clientConfig, err := configFromEnv("peer")
    30  	if err != nil {
    31  		return nil, errors.WithMessage(err, "failed to load config for PeerClient")
    32  	}
    33  	return newPeerClientForClientConfig(address, clientConfig)
    34  }
    35  
    36  // NewPeerClientForAddress creates an instance of a PeerClient using the
    37  // provided peer address and, if TLS is enabled, the TLS root cert file
    38  func NewPeerClientForAddress(address, tlsRootCertFile string) (*PeerClient, error) {
    39  	if address == "" {
    40  		return nil, errors.New("peer address must be set")
    41  	}
    42  
    43  	clientConfig := comm.ClientConfig{}
    44  	clientConfig.DialTimeout = viper.GetDuration("peer.client.connTimeout")
    45  	if clientConfig.DialTimeout == time.Duration(0) {
    46  		clientConfig.DialTimeout = defaultConnTimeout
    47  	}
    48  
    49  	secOpts := comm.SecureOptions{
    50  		UseTLS:             viper.GetBool("peer.tls.enabled"),
    51  		RequireClientCert:  viper.GetBool("peer.tls.clientAuthRequired"),
    52  		ServerNameOverride: viper.GetString("peer.tls.serverhostoverride"),
    53  	}
    54  
    55  	if secOpts.RequireClientCert {
    56  		var err error
    57  		secOpts.Key, secOpts.Certificate, err = getClientAuthInfoFromEnv("peer")
    58  		if err != nil {
    59  			return nil, err
    60  		}
    61  
    62  	}
    63  	clientConfig.SecOpts = secOpts
    64  
    65  	if clientConfig.SecOpts.UseTLS {
    66  		if tlsRootCertFile == "" {
    67  			return nil, errors.New("tls root cert file must be set")
    68  		}
    69  		caPEM, res := ioutil.ReadFile(tlsRootCertFile)
    70  		if res != nil {
    71  			return nil, errors.WithMessagef(res, "unable to load TLS root cert file from %s", tlsRootCertFile)
    72  		}
    73  		clientConfig.SecOpts.ServerRootCAs = [][]byte{caPEM}
    74  	}
    75  
    76  	clientConfig.MaxRecvMsgSize = comm.DefaultMaxRecvMsgSize
    77  	if viper.IsSet("peer.maxRecvMsgSize") {
    78  		clientConfig.MaxRecvMsgSize = int(viper.GetInt32("peer.maxRecvMsgSize"))
    79  	}
    80  	clientConfig.MaxSendMsgSize = comm.DefaultMaxSendMsgSize
    81  	if viper.IsSet("peer.maxSendMsgSize") {
    82  		clientConfig.MaxSendMsgSize = int(viper.GetInt32("peer.maxSendMsgSize"))
    83  	}
    84  
    85  	return newPeerClientForClientConfig(address, clientConfig)
    86  }
    87  
    88  func newPeerClientForClientConfig(address string, clientConfig comm.ClientConfig) (*PeerClient, error) {
    89  	// set the default keepalive options to match the server
    90  	clientConfig.KaOpts = comm.DefaultKeepaliveOptions
    91  	cc, err := newCommonClient(address, clientConfig)
    92  	if err != nil {
    93  		return nil, errors.WithMessage(err, "failed to create PeerClient from config")
    94  	}
    95  	return &PeerClient{CommonClient: cc}, 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.clientConfig.Dial(pc.address)
   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.clientConfig.Dial(pc.address)
   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.clientConfig.Dial(pc.address)
   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  	peerClient, err := newPeerClient(address, tlsRootCertFile)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	return peerClient.Endorser()
   141  }
   142  
   143  // GetClientCertificate returns the client's TLS certificate
   144  func GetClientCertificate() (tls.Certificate, error) {
   145  	if !viper.GetBool("peer.tls.clientAuthRequired") {
   146  		return tls.Certificate{}, nil
   147  	}
   148  
   149  	key, certificate, err := getClientAuthInfoFromEnv("peer")
   150  	if err != nil {
   151  		return tls.Certificate{}, err
   152  	}
   153  
   154  	cert, err := tls.X509KeyPair(certificate, key)
   155  	if err != nil {
   156  		return tls.Certificate{}, errors.WithMessage(err, "failed to load client certificate")
   157  	}
   158  	return cert, nil
   159  }
   160  
   161  // GetDeliverClient returns a new deliver client. If both the address and
   162  // tlsRootCertFile are not provided, the target values for the client are taken
   163  // from the configuration settings for "peer.address" and
   164  // "peer.tls.rootcert.file"
   165  func GetDeliverClient(address, tlsRootCertFile string) (pb.Deliver_DeliverClient, error) {
   166  	peerClient, err := newPeerClient(address, tlsRootCertFile)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	return peerClient.Deliver()
   171  }
   172  
   173  // GetPeerDeliverClient returns a new deliver client. If both the address and
   174  // tlsRootCertFile are not provided, the target values for the client are taken
   175  // from the configuration settings for "peer.address" and
   176  // "peer.tls.rootcert.file"
   177  func GetPeerDeliverClient(address, tlsRootCertFile string) (pb.DeliverClient, error) {
   178  	peerClient, err := newPeerClient(address, tlsRootCertFile)
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  	return peerClient.PeerDeliver()
   183  }
   184  
   185  // SnapshotClient returns a client for the snapshot service
   186  func (pc *PeerClient) SnapshotClient() (pb.SnapshotClient, error) {
   187  	conn, err := pc.CommonClient.clientConfig.Dial(pc.address)
   188  	if err != nil {
   189  		return nil, errors.WithMessagef(err, "snapshot client failed to connect to %s", pc.address)
   190  	}
   191  	return pb.NewSnapshotClient(conn), nil
   192  }
   193  
   194  // GetSnapshotClient returns a new snapshot client. If both the address and
   195  // tlsRootCertFile are not provided, the target values for the client are taken
   196  // from the configuration settings for "peer.address" and
   197  // "peer.tls.rootcert.file"
   198  func GetSnapshotClient(address, tlsRootCertFile string) (pb.SnapshotClient, error) {
   199  	peerClient, err := newPeerClient(address, tlsRootCertFile)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  	return peerClient.SnapshotClient()
   204  }
   205  
   206  func newPeerClient(address, tlsRootCertFile string) (*PeerClient, error) {
   207  	if address != "" {
   208  		return NewPeerClientForAddress(address, tlsRootCertFile)
   209  	}
   210  	return NewPeerClientFromEnv()
   211  }