go_study/fabric-main/internal/peer/common/peerclient.go

212 lines
6.9 KiB
Go

/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package common
import (
"context"
"crypto/tls"
"io/ioutil"
"time"
pb "github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/internal/pkg/comm"
"github.com/pkg/errors"
"github.com/spf13/viper"
)
// PeerClient represents a client for communicating with a peer
type PeerClient struct {
*CommonClient
}
// NewPeerClientFromEnv creates an instance of a PeerClient from the global
// Viper instance
func NewPeerClientFromEnv() (*PeerClient, error) {
address, clientConfig, err := configFromEnv("peer")
if err != nil {
return nil, errors.WithMessage(err, "failed to load config for PeerClient")
}
return newPeerClientForClientConfig(address, clientConfig)
}
// NewPeerClientForAddress creates an instance of a PeerClient using the
// provided peer address and, if TLS is enabled, the TLS root cert file
func NewPeerClientForAddress(address, tlsRootCertFile string) (*PeerClient, error) {
if address == "" {
return nil, errors.New("peer address must be set")
}
clientConfig := comm.ClientConfig{}
clientConfig.DialTimeout = viper.GetDuration("peer.client.connTimeout")
if clientConfig.DialTimeout == time.Duration(0) {
clientConfig.DialTimeout = defaultConnTimeout
}
secOpts := comm.SecureOptions{
UseTLS: viper.GetBool("peer.tls.enabled"),
RequireClientCert: viper.GetBool("peer.tls.clientAuthRequired"),
ServerNameOverride: viper.GetString("peer.tls.serverhostoverride"),
}
if secOpts.RequireClientCert {
var err error
secOpts.Key, secOpts.Certificate, err = getClientAuthInfoFromEnv("peer")
if err != nil {
return nil, err
}
}
clientConfig.SecOpts = secOpts
if clientConfig.SecOpts.UseTLS {
if tlsRootCertFile == "" {
return nil, errors.New("tls root cert file must be set")
}
caPEM, res := ioutil.ReadFile(tlsRootCertFile)
if res != nil {
return nil, errors.WithMessagef(res, "unable to load TLS root cert file from %s", tlsRootCertFile)
}
clientConfig.SecOpts.ServerRootCAs = [][]byte{caPEM}
}
clientConfig.MaxRecvMsgSize = comm.DefaultMaxRecvMsgSize
if viper.IsSet("peer.maxRecvMsgSize") {
clientConfig.MaxRecvMsgSize = int(viper.GetInt32("peer.maxRecvMsgSize"))
}
clientConfig.MaxSendMsgSize = comm.DefaultMaxSendMsgSize
if viper.IsSet("peer.maxSendMsgSize") {
clientConfig.MaxSendMsgSize = int(viper.GetInt32("peer.maxSendMsgSize"))
}
return newPeerClientForClientConfig(address, clientConfig)
}
func newPeerClientForClientConfig(address string, clientConfig comm.ClientConfig) (*PeerClient, error) {
// set the default keepalive options to match the server
clientConfig.KaOpts = comm.DefaultKeepaliveOptions
cc, err := newCommonClient(address, clientConfig)
if err != nil {
return nil, errors.WithMessage(err, "failed to create PeerClient from config")
}
return &PeerClient{CommonClient: cc}, nil
}
// Endorser returns a client for the Endorser service
func (pc *PeerClient) Endorser() (pb.EndorserClient, error) {
conn, err := pc.CommonClient.clientConfig.Dial(pc.address)
if err != nil {
return nil, errors.WithMessagef(err, "endorser client failed to connect to %s", pc.address)
}
return pb.NewEndorserClient(conn), nil
}
// Deliver returns a client for the Deliver service
func (pc *PeerClient) Deliver() (pb.Deliver_DeliverClient, error) {
conn, err := pc.CommonClient.clientConfig.Dial(pc.address)
if err != nil {
return nil, errors.WithMessagef(err, "deliver client failed to connect to %s", pc.address)
}
return pb.NewDeliverClient(conn).Deliver(context.TODO())
}
// PeerDeliver returns a client for the Deliver service for peer-specific use
// cases (i.e. DeliverFiltered)
func (pc *PeerClient) PeerDeliver() (pb.DeliverClient, error) {
conn, err := pc.CommonClient.clientConfig.Dial(pc.address)
if err != nil {
return nil, errors.WithMessagef(err, "deliver client failed to connect to %s", pc.address)
}
return pb.NewDeliverClient(conn), nil
}
// Certificate returns the TLS client certificate (if available)
func (pc *PeerClient) Certificate() tls.Certificate {
return pc.CommonClient.Certificate()
}
// GetEndorserClient returns a new endorser client. If the both the address and
// tlsRootCertFile are not provided, the target values for the client are taken
// from the configuration settings for "peer.address" and
// "peer.tls.rootcert.file"
func GetEndorserClient(address, tlsRootCertFile string) (pb.EndorserClient, error) {
peerClient, err := newPeerClient(address, tlsRootCertFile)
if err != nil {
return nil, err
}
return peerClient.Endorser()
}
// GetClientCertificate returns the client's TLS certificate
func GetClientCertificate() (tls.Certificate, error) {
if !viper.GetBool("peer.tls.clientAuthRequired") {
return tls.Certificate{}, nil
}
key, certificate, err := getClientAuthInfoFromEnv("peer")
if err != nil {
return tls.Certificate{}, err
}
cert, err := tls.X509KeyPair(certificate, key)
if err != nil {
return tls.Certificate{}, errors.WithMessage(err, "failed to load client certificate")
}
return cert, nil
}
// GetDeliverClient returns a new deliver client. If both the address and
// tlsRootCertFile are not provided, the target values for the client are taken
// from the configuration settings for "peer.address" and
// "peer.tls.rootcert.file"
func GetDeliverClient(address, tlsRootCertFile string) (pb.Deliver_DeliverClient, error) {
peerClient, err := newPeerClient(address, tlsRootCertFile)
if err != nil {
return nil, err
}
return peerClient.Deliver()
}
// GetPeerDeliverClient returns a new deliver client. If both the address and
// tlsRootCertFile are not provided, the target values for the client are taken
// from the configuration settings for "peer.address" and
// "peer.tls.rootcert.file"
func GetPeerDeliverClient(address, tlsRootCertFile string) (pb.DeliverClient, error) {
peerClient, err := newPeerClient(address, tlsRootCertFile)
if err != nil {
return nil, err
}
return peerClient.PeerDeliver()
}
// SnapshotClient returns a client for the snapshot service
func (pc *PeerClient) SnapshotClient() (pb.SnapshotClient, error) {
conn, err := pc.CommonClient.clientConfig.Dial(pc.address)
if err != nil {
return nil, errors.WithMessagef(err, "snapshot client failed to connect to %s", pc.address)
}
return pb.NewSnapshotClient(conn), nil
}
// GetSnapshotClient returns a new snapshot client. If both the address and
// tlsRootCertFile are not provided, the target values for the client are taken
// from the configuration settings for "peer.address" and
// "peer.tls.rootcert.file"
func GetSnapshotClient(address, tlsRootCertFile string) (pb.SnapshotClient, error) {
peerClient, err := newPeerClient(address, tlsRootCertFile)
if err != nil {
return nil, err
}
return peerClient.SnapshotClient()
}
func newPeerClient(address, tlsRootCertFile string) (*PeerClient, error) {
if address != "" {
return NewPeerClientForAddress(address, tlsRootCertFile)
}
return NewPeerClientFromEnv()
}