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 }