go.temporal.io/server@v1.23.0/common/rpc/rpc.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package rpc 26 27 import ( 28 "crypto/tls" 29 "net" 30 "sync" 31 32 "google.golang.org/grpc" 33 "google.golang.org/grpc/credentials" 34 35 "go.temporal.io/server/common" 36 "go.temporal.io/server/common/config" 37 "go.temporal.io/server/common/convert" 38 "go.temporal.io/server/common/log" 39 "go.temporal.io/server/common/log/tag" 40 "go.temporal.io/server/common/primitives" 41 "go.temporal.io/server/common/rpc/encryption" 42 "go.temporal.io/server/environment" 43 ) 44 45 var _ common.RPCFactory = (*RPCFactory)(nil) 46 47 // RPCFactory is an implementation of common.RPCFactory interface 48 type RPCFactory struct { 49 config *config.RPC 50 serviceName primitives.ServiceName 51 logger log.Logger 52 53 frontendURL string 54 frontendTLSConfig *tls.Config 55 56 initListener sync.Once 57 grpcListener net.Listener 58 tlsFactory encryption.TLSConfigProvider 59 clientInterceptors []grpc.UnaryClientInterceptor 60 } 61 62 // NewFactory builds a new RPCFactory 63 // conforming to the underlying configuration 64 func NewFactory( 65 cfg *config.RPC, 66 sName primitives.ServiceName, 67 logger log.Logger, 68 tlsProvider encryption.TLSConfigProvider, 69 frontendURL string, 70 frontendTLSConfig *tls.Config, 71 clientInterceptors []grpc.UnaryClientInterceptor, 72 ) *RPCFactory { 73 return &RPCFactory{ 74 config: cfg, 75 serviceName: sName, 76 logger: logger, 77 frontendURL: frontendURL, 78 frontendTLSConfig: frontendTLSConfig, 79 tlsFactory: tlsProvider, 80 clientInterceptors: clientInterceptors, 81 } 82 } 83 84 func (d *RPCFactory) GetFrontendGRPCServerOptions() ([]grpc.ServerOption, error) { 85 var opts []grpc.ServerOption 86 87 if d.tlsFactory != nil { 88 serverConfig, err := d.tlsFactory.GetFrontendServerConfig() 89 if err != nil { 90 return nil, err 91 } 92 if serverConfig == nil { 93 return opts, nil 94 } 95 opts = append(opts, grpc.Creds(credentials.NewTLS(serverConfig))) 96 } 97 98 return opts, nil 99 } 100 101 func (d *RPCFactory) GetFrontendClientTlsConfig() (*tls.Config, error) { 102 if d.tlsFactory != nil { 103 return d.tlsFactory.GetFrontendClientConfig() 104 } 105 106 return nil, nil 107 } 108 109 func (d *RPCFactory) GetRemoteClusterClientConfig(hostname string) (*tls.Config, error) { 110 if d.tlsFactory != nil { 111 return d.tlsFactory.GetRemoteClusterClientConfig(hostname) 112 } 113 114 return nil, nil 115 } 116 117 func (d *RPCFactory) GetInternodeGRPCServerOptions() ([]grpc.ServerOption, error) { 118 var opts []grpc.ServerOption 119 120 if d.tlsFactory != nil { 121 serverConfig, err := d.tlsFactory.GetInternodeServerConfig() 122 if err != nil { 123 return nil, err 124 } 125 if serverConfig == nil { 126 return opts, nil 127 } 128 opts = append(opts, grpc.Creds(credentials.NewTLS(serverConfig))) 129 } 130 131 return opts, nil 132 } 133 134 func (d *RPCFactory) GetInternodeClientTlsConfig() (*tls.Config, error) { 135 if d.tlsFactory != nil { 136 return d.tlsFactory.GetInternodeClientConfig() 137 } 138 139 return nil, nil 140 } 141 142 // GetGRPCListener returns cached dispatcher for gRPC inbound or creates one 143 func (d *RPCFactory) GetGRPCListener() net.Listener { 144 d.initListener.Do(func() { 145 hostAddress := net.JoinHostPort(getListenIP(d.config, d.logger).String(), convert.IntToString(d.config.GRPCPort)) 146 var err error 147 d.grpcListener, err = net.Listen("tcp", hostAddress) 148 149 if err != nil { 150 d.logger.Fatal("Failed to start gRPC listener", tag.Error(err), tag.Service(d.serviceName), tag.Address(hostAddress)) 151 } 152 153 d.logger.Info("Created gRPC listener", tag.Service(d.serviceName), tag.Address(hostAddress)) 154 }) 155 156 return d.grpcListener 157 } 158 159 func getListenIP(cfg *config.RPC, logger log.Logger) net.IP { 160 if cfg.BindOnLocalHost && len(cfg.BindOnIP) > 0 { 161 logger.Fatal("ListenIP failed, bindOnLocalHost and bindOnIP are mutually exclusive") 162 return nil 163 } 164 165 if cfg.BindOnLocalHost { 166 return net.ParseIP(environment.GetLocalhostIP()) 167 } 168 169 if len(cfg.BindOnIP) > 0 { 170 ip := net.ParseIP(cfg.BindOnIP) 171 if ip != nil { 172 return ip 173 } 174 logger.Fatal("ListenIP failed, unable to parse bindOnIP value", tag.Address(cfg.BindOnIP)) 175 return nil 176 } 177 ip, err := config.ListenIP() 178 if err != nil { 179 logger.Fatal("ListenIP failed", tag.Error(err)) 180 return nil 181 } 182 return ip 183 } 184 185 // CreateRemoteFrontendGRPCConnection creates connection for gRPC calls 186 func (d *RPCFactory) CreateRemoteFrontendGRPCConnection(rpcAddress string) *grpc.ClientConn { 187 var tlsClientConfig *tls.Config 188 var err error 189 if d.tlsFactory != nil { 190 hostname, _, err2 := net.SplitHostPort(rpcAddress) 191 if err2 != nil { 192 d.logger.Fatal("Invalid rpcAddress for remote cluster", tag.Error(err2)) 193 } 194 tlsClientConfig, err = d.tlsFactory.GetRemoteClusterClientConfig(hostname) 195 196 if err != nil { 197 d.logger.Fatal("Failed to create tls config for gRPC connection", tag.Error(err)) 198 return nil 199 } 200 } 201 202 return d.dial(rpcAddress, tlsClientConfig) 203 } 204 205 // CreateLocalFrontendGRPCConnection creates connection for internal frontend calls 206 func (d *RPCFactory) CreateLocalFrontendGRPCConnection() *grpc.ClientConn { 207 return d.dial(d.frontendURL, d.frontendTLSConfig) 208 } 209 210 // CreateInternodeGRPCConnection creates connection for gRPC calls 211 func (d *RPCFactory) CreateInternodeGRPCConnection(hostName string) *grpc.ClientConn { 212 var tlsClientConfig *tls.Config 213 var err error 214 if d.tlsFactory != nil { 215 tlsClientConfig, err = d.tlsFactory.GetInternodeClientConfig() 216 if err != nil { 217 d.logger.Fatal("Failed to create tls config for gRPC connection", tag.Error(err)) 218 return nil 219 } 220 } 221 222 return d.dial(hostName, tlsClientConfig) 223 } 224 225 func (d *RPCFactory) dial(hostName string, tlsClientConfig *tls.Config) *grpc.ClientConn { 226 connection, err := Dial(hostName, tlsClientConfig, d.logger, d.clientInterceptors...) 227 if err != nil { 228 d.logger.Fatal("Failed to create gRPC connection", tag.Error(err)) 229 return nil 230 } 231 232 return connection 233 } 234 235 func (d *RPCFactory) GetTLSConfigProvider() encryption.TLSConfigProvider { 236 return d.tlsFactory 237 }