github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/access/rpc/connection/connection.go (about)

     1  package connection
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net"
     7  	"time"
     8  
     9  	"github.com/onflow/crypto"
    10  	"github.com/onflow/flow/protobuf/go/flow/access"
    11  	"github.com/onflow/flow/protobuf/go/flow/execution"
    12  	"github.com/rs/zerolog"
    13  
    14  	"github.com/onflow/flow-go/module"
    15  )
    16  
    17  // ConnectionFactory is an interface for creating access and execution API clients.
    18  type ConnectionFactory interface {
    19  	// GetAccessAPIClient gets an access API client for the specified address using the default CollectionGRPCPort, networkPubKey is optional,
    20  	// and it is used for secure gRPC connection. Can be nil for an unsecured connection.
    21  	// The returned io.Closer should close the connection after the call if no error occurred during client creation.
    22  	GetAccessAPIClient(address string, networkPubKey crypto.PublicKey) (access.AccessAPIClient, io.Closer, error)
    23  	// GetAccessAPIClientWithPort gets an access API client for the specified address with port, networkPubKey is optional,
    24  	// and it is used for secure gRPC connection. Can be nil for an unsecured connection.
    25  	// The returned io.Closer should close the connection after the call if no error occurred during client creation.
    26  	GetAccessAPIClientWithPort(address string, networkPubKey crypto.PublicKey) (access.AccessAPIClient, io.Closer, error)
    27  	// GetExecutionAPIClient gets an execution API client for the specified address using the default ExecutionGRPCPort.
    28  	// The returned io.Closer should close the connection after the call if no error occurred during client creation.
    29  	GetExecutionAPIClient(address string) (execution.ExecutionAPIClient, io.Closer, error)
    30  }
    31  
    32  // ProxyConnectionFactory wraps an existing ConnectionFactory and allows getting API clients for a target address.
    33  type ProxyConnectionFactory struct {
    34  	ConnectionFactory
    35  	targetAddress string
    36  }
    37  
    38  // GetAccessAPIClient gets an access API client for a target address using the default CollectionGRPCPort.
    39  // The networkPubKey is the public key used for a secure gRPC connection. It can be nil for an unsecured connection.
    40  // The returned io.Closer should close the connection after the call if no error occurred during client creation.
    41  func (p *ProxyConnectionFactory) GetAccessAPIClient(address string, networkPubKey crypto.PublicKey) (access.AccessAPIClient, io.Closer, error) {
    42  	return p.ConnectionFactory.GetAccessAPIClient(p.targetAddress, networkPubKey)
    43  }
    44  
    45  // GetExecutionAPIClient gets an execution API client for a target address using the default ExecutionGRPCPort.
    46  // The returned io.Closer should close the connection after the call if no error occurred during client creation.
    47  func (p *ProxyConnectionFactory) GetExecutionAPIClient(address string) (execution.ExecutionAPIClient, io.Closer, error) {
    48  	return p.ConnectionFactory.GetExecutionAPIClient(p.targetAddress)
    49  }
    50  
    51  var _ ConnectionFactory = (*ConnectionFactoryImpl)(nil)
    52  
    53  type ConnectionFactoryImpl struct {
    54  	CollectionGRPCPort        uint
    55  	ExecutionGRPCPort         uint
    56  	CollectionNodeGRPCTimeout time.Duration
    57  	ExecutionNodeGRPCTimeout  time.Duration
    58  	AccessMetrics             module.AccessMetrics
    59  	Log                       zerolog.Logger
    60  	Manager                   Manager
    61  }
    62  
    63  // GetAccessAPIClient gets an access API client for the specified address using the default CollectionGRPCPort.
    64  // The networkPubKey is the public key used for secure gRPC connection. Can be nil for an unsecured connection.
    65  // The returned io.Closer should close the connection after the call if no error occurred during client creation.
    66  func (cf *ConnectionFactoryImpl) GetAccessAPIClient(address string, networkPubKey crypto.PublicKey) (access.AccessAPIClient, io.Closer, error) {
    67  	address, err := getGRPCAddress(address, cf.CollectionGRPCPort)
    68  	if err != nil {
    69  		return nil, nil, err
    70  	}
    71  	return cf.GetAccessAPIClientWithPort(address, networkPubKey)
    72  }
    73  
    74  // GetAccessAPIClientWithPort gets an access API client for the specified address with port.
    75  // The networkPubKey is the public key used for secure gRPC connection. Can be nil for an unsecured connection.
    76  // The returned io.Closer should close the connection after the call if no error occurred during client creation.
    77  func (cf *ConnectionFactoryImpl) GetAccessAPIClientWithPort(address string, networkPubKey crypto.PublicKey) (access.AccessAPIClient, io.Closer, error) {
    78  	conn, closer, err := cf.Manager.GetConnection(address, cf.CollectionNodeGRPCTimeout, networkPubKey)
    79  	if err != nil {
    80  		return nil, nil, err
    81  	}
    82  
    83  	return access.NewAccessAPIClient(conn), closer, nil
    84  }
    85  
    86  // GetExecutionAPIClient gets an execution API client for the specified address using the default ExecutionGRPCPort.
    87  // The returned io.Closer should close the connection after the call if no error occurred during client creation.
    88  func (cf *ConnectionFactoryImpl) GetExecutionAPIClient(address string) (execution.ExecutionAPIClient, io.Closer, error) {
    89  	grpcAddress, err := getGRPCAddress(address, cf.ExecutionGRPCPort)
    90  	if err != nil {
    91  		return nil, nil, err
    92  	}
    93  
    94  	conn, closer, err := cf.Manager.GetConnection(grpcAddress, cf.ExecutionNodeGRPCTimeout, nil)
    95  	if err != nil {
    96  		return nil, nil, err
    97  	}
    98  
    99  	return execution.NewExecutionAPIClient(conn), closer, nil
   100  }
   101  
   102  // getGRPCAddress translates the flow.Identity address to the GRPC address of the node by switching the port to the
   103  // GRPC port from the libp2p port.
   104  func getGRPCAddress(address string, grpcPort uint) (string, error) {
   105  	// Split hostname and port
   106  	hostnameOrIP, _, err := net.SplitHostPort(address)
   107  	if err != nil {
   108  		return "", err
   109  	}
   110  	// Use the hostname from the identity list and the GRPC port number as the one passed in as an argument.
   111  	grpcAddress := fmt.Sprintf("%s:%d", hostnameOrIP, grpcPort)
   112  
   113  	return grpcAddress, nil
   114  }