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 }