133 lines
3.5 KiB
Go
133 lines
3.5 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package discovery
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/hyperledger/fabric-protos-go/discovery"
|
|
"github.com/hyperledger/fabric/cmd/common"
|
|
"github.com/hyperledger/fabric/cmd/common/comm"
|
|
"github.com/hyperledger/fabric/cmd/common/signer"
|
|
discoveryclient "github.com/hyperledger/fabric/discovery/client"
|
|
"github.com/hyperledger/fabric/protoutil"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
//go:generate mockery -dir . -name LocalResponse -case underscore -output mocks/
|
|
|
|
// LocalResponse is the local interface used to generate mocks for foreign interface.
|
|
type LocalResponse interface {
|
|
discoveryclient.LocalResponse
|
|
}
|
|
|
|
//go:generate mockery -dir . -name ChannelResponse -case underscore -output mocks/
|
|
|
|
// ChannelResponse is the local interface used to generate mocks for foreign interface.
|
|
type ChannelResponse interface {
|
|
discoveryclient.ChannelResponse
|
|
}
|
|
|
|
//go:generate mockery -dir . -name ServiceResponse -case underscore -output mocks/
|
|
|
|
// ServiceResponse represents a response sent from the discovery service
|
|
type ServiceResponse interface {
|
|
// ForChannel returns a ChannelResponse in the context of a given channel
|
|
ForChannel(string) discoveryclient.ChannelResponse
|
|
|
|
// ForLocal returns a LocalResponse in the context of no channel
|
|
ForLocal() discoveryclient.LocalResponse
|
|
|
|
// Raw returns the raw response from the server
|
|
Raw() *discovery.Response
|
|
}
|
|
|
|
type response struct {
|
|
raw *discovery.Response
|
|
discoveryclient.Response
|
|
}
|
|
|
|
func (r *response) Raw() *discovery.Response {
|
|
return r.raw
|
|
}
|
|
|
|
// ClientStub is a stub that communicates with the discovery service
|
|
// using the discovery client implementation
|
|
type ClientStub struct{}
|
|
|
|
// Send sends the request, and receives a response
|
|
func (stub *ClientStub) Send(server string, conf common.Config, req *discoveryclient.Request) (ServiceResponse, error) {
|
|
comm, err := comm.NewClient(conf.TLSConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
signer, err := signer.NewSigner(conf.SignerConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
timeout, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
|
defer cancel()
|
|
|
|
disc := discoveryclient.NewClient(comm.NewDialer(server), signer.Sign, 0)
|
|
|
|
resp, err := disc.Send(timeout, req, &discovery.AuthInfo{
|
|
ClientIdentity: signer.Creator,
|
|
ClientTlsCertHash: comm.TLSCertHash,
|
|
})
|
|
if err != nil {
|
|
return nil, errors.Errorf("failed connecting to %s: %v", server, err)
|
|
}
|
|
return &response{
|
|
Response: resp,
|
|
}, nil
|
|
}
|
|
|
|
// RawStub is a stub that communicates with the discovery service
|
|
// without any intermediary.
|
|
type RawStub struct{}
|
|
|
|
// Send sends the request, and receives a response
|
|
func (stub *RawStub) Send(server string, conf common.Config, req *discoveryclient.Request) (ServiceResponse, error) {
|
|
comm, err := comm.NewClient(conf.TLSConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
signer, err := signer.NewSigner(conf.SignerConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
timeout, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
|
defer cancel()
|
|
|
|
req.Authentication = &discovery.AuthInfo{
|
|
ClientIdentity: signer.Creator,
|
|
ClientTlsCertHash: comm.TLSCertHash,
|
|
}
|
|
|
|
payload := protoutil.MarshalOrPanic(req.Request)
|
|
sig, err := signer.Sign(payload)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cc, err := comm.NewDialer(server)()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp, err := discovery.NewDiscoveryClient(cc).Discover(timeout, &discovery.SignedRequest{
|
|
Payload: payload,
|
|
Signature: sig,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &response{
|
|
raw: resp,
|
|
}, nil
|
|
}
|