// startWalletRPCServices associates each of the (optionally-nil) RPC servers // with a wallet to enable remote wallet access. For the GRPC server, this // registers the WalletService service, and for the legacy JSON-RPC server it // enables methods that require a loaded wallet. func startWalletRPCServices(wallet *wallet.Wallet, server *grpc.Server, legacyServer *legacyrpc.Server) { if server != nil { rpcserver.StartWalletService(server, wallet) } if legacyServer != nil { legacyServer.RegisterWallet(wallet) } }
// rpcClientConnectLoop continuously attempts a connection to the consensus RPC // server. When a connection is established, the client is used to sync the // loaded wallet, either immediately or when loaded at a later time. // // The legacy RPC is optional. If set, the connected RPC client will be // associated with the server for RPC passthrough and to enable additional // methods. func rpcClientConnectLoop(legacyRPCServer *legacyrpc.Server, loader *wallet.Loader) { certs := readCAFile() for { chainClient, err := startChainRPC(certs) if err != nil { log.Errorf("Unable to open connection to consensus RPC server: %v", err) continue } // Rather than inlining this logic directly into the loader // callback, a function variable is used to avoid running any of // this after the client disconnects by setting it to nil. This // prevents the callback from associating a wallet loaded at a // later time with a client that has already disconnected. A // mutex is used to make this concurrent safe. associateRPCClient := func(w *wallet.Wallet) { w.SynchronizeRPC(chainClient) if legacyRPCServer != nil { legacyRPCServer.SetChainServer(chainClient) } } mu := new(sync.Mutex) loader.RunAfterLoad(func(w *wallet.Wallet) { mu.Lock() associate := associateRPCClient mu.Unlock() if associate != nil { associate(w) } }) chainClient.WaitForShutdown() mu.Lock() associateRPCClient = nil mu.Unlock() loadedWallet, ok := loader.LoadedWallet() if ok { // Do not attempt a reconnect when the wallet was // explicitly stopped. if loadedWallet.ShuttingDown() { return } loadedWallet.SetChainSynced(false) // TODO: Rework the wallet so changing the RPC client // does not require stopping and restarting everything. loadedWallet.Stop() loadedWallet.WaitForShutdown() loadedWallet.Start() } } }