Merge pull request #3775 from halseth/mobile-listener-signal
[mobile] make Ready signal for custom listeners
This commit is contained in:
commit
f0bd4e775b
48
lnd.go
48
lnd.go
@ -59,16 +59,25 @@ var (
|
|||||||
networkDir string
|
networkDir string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ListnerWithSignal is a net.Listner that has an additional Ready channel that
|
||||||
|
// will be closed when a server starts listening.
|
||||||
|
type ListenerWithSignal struct {
|
||||||
|
net.Listener
|
||||||
|
|
||||||
|
// Ready will be closed by the server listening on Listener.
|
||||||
|
Ready chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
// ListenerCfg is a wrapper around custom listeners that can be passed to lnd
|
// ListenerCfg is a wrapper around custom listeners that can be passed to lnd
|
||||||
// when calling its main method.
|
// when calling its main method.
|
||||||
type ListenerCfg struct {
|
type ListenerCfg struct {
|
||||||
// WalletUnlocker can be set to the listener to use for the wallet
|
// WalletUnlocker can be set to the listener to use for the wallet
|
||||||
// unlocker. If nil a regular network listener will be created.
|
// unlocker. If nil a regular network listener will be created.
|
||||||
WalletUnlocker net.Listener
|
WalletUnlocker *ListenerWithSignal
|
||||||
|
|
||||||
// RPCListener can be set to the listener to use for the RPC server. If
|
// RPCListener can be set to the listener to use for the RPC server. If
|
||||||
// nil a regular network listener will be created.
|
// nil a regular network listener will be created.
|
||||||
RPCListener net.Listener
|
RPCListener *ListenerWithSignal
|
||||||
}
|
}
|
||||||
|
|
||||||
// rpcListeners is a function type used for closures that fetches a set of RPC
|
// rpcListeners is a function type used for closures that fetches a set of RPC
|
||||||
@ -76,7 +85,8 @@ type ListenerCfg struct {
|
|||||||
// with these listeners. If no custom listeners are present, this should return
|
// with these listeners. If no custom listeners are present, this should return
|
||||||
// normal listeners from the RPC endpoints defined in the config, and server
|
// normal listeners from the RPC endpoints defined in the config, and server
|
||||||
// options specifying TLS.
|
// options specifying TLS.
|
||||||
type rpcListeners func() ([]net.Listener, func(), []grpc.ServerOption, error)
|
type rpcListeners func() ([]*ListenerWithSignal, func(), []grpc.ServerOption,
|
||||||
|
error)
|
||||||
|
|
||||||
// Main is the true entry point for lnd. This function is required since defers
|
// Main is the true entry point for lnd. This function is required since defers
|
||||||
// created in the top-level scope of a main method aren't executed if os.Exit()
|
// created in the top-level scope of a main method aren't executed if os.Exit()
|
||||||
@ -235,10 +245,10 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// getListeners is a closure that creates listeners from the
|
// getListeners is a closure that creates listeners from the
|
||||||
// RPCListeners defined in the config. It also returns a cleanup
|
// RPCListeners defined in the config. It also returns a cleanup
|
||||||
// closure and the server options to use for the GRPC server.
|
// closure and the server options to use for the GRPC server.
|
||||||
getListeners := func() ([]net.Listener, func(), []grpc.ServerOption,
|
getListeners := func() ([]*ListenerWithSignal, func(),
|
||||||
error) {
|
[]grpc.ServerOption, error) {
|
||||||
|
|
||||||
var grpcListeners []net.Listener
|
var grpcListeners []*ListenerWithSignal
|
||||||
for _, grpcEndpoint := range cfg.RPCListeners {
|
for _, grpcEndpoint := range cfg.RPCListeners {
|
||||||
// Start a gRPC server listening for HTTP/2
|
// Start a gRPC server listening for HTTP/2
|
||||||
// connections.
|
// connections.
|
||||||
@ -248,7 +258,11 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
grpcEndpoint)
|
grpcEndpoint)
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
grpcListeners = append(grpcListeners, lis)
|
grpcListeners = append(
|
||||||
|
grpcListeners, &ListenerWithSignal{
|
||||||
|
Listener: lis,
|
||||||
|
Ready: make(chan struct{}),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup := func() {
|
cleanup := func() {
|
||||||
@ -262,7 +276,7 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// walletUnlockerListeners is a closure we'll hand to the wallet
|
// walletUnlockerListeners is a closure we'll hand to the wallet
|
||||||
// unlocker, that will be called when it needs listeners for its GPRC
|
// unlocker, that will be called when it needs listeners for its GPRC
|
||||||
// server.
|
// server.
|
||||||
walletUnlockerListeners := func() ([]net.Listener, func(),
|
walletUnlockerListeners := func() ([]*ListenerWithSignal, func(),
|
||||||
[]grpc.ServerOption, error) {
|
[]grpc.ServerOption, error) {
|
||||||
|
|
||||||
// If we have chosen to start with a dedicated listener for the
|
// If we have chosen to start with a dedicated listener for the
|
||||||
@ -271,8 +285,8 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// TODO(halseth): any point in adding TLS support for custom
|
// TODO(halseth): any point in adding TLS support for custom
|
||||||
// listeners?
|
// listeners?
|
||||||
if lisCfg.WalletUnlocker != nil {
|
if lisCfg.WalletUnlocker != nil {
|
||||||
return []net.Listener{lisCfg.WalletUnlocker}, func() {},
|
return []*ListenerWithSignal{lisCfg.WalletUnlocker},
|
||||||
[]grpc.ServerOption{}, nil
|
func() {}, []grpc.ServerOption{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we'll return the regular listeners.
|
// Otherwise we'll return the regular listeners.
|
||||||
@ -501,8 +515,8 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
|
|
||||||
// rpcListeners is a closure we'll hand to the rpc server, that will be
|
// rpcListeners is a closure we'll hand to the rpc server, that will be
|
||||||
// called when it needs listeners for its GPRC server.
|
// called when it needs listeners for its GPRC server.
|
||||||
rpcListeners := func() ([]net.Listener, func(), []grpc.ServerOption,
|
rpcListeners := func() ([]*ListenerWithSignal, func(),
|
||||||
error) {
|
[]grpc.ServerOption, error) {
|
||||||
|
|
||||||
// If we have chosen to start with a dedicated listener for the
|
// If we have chosen to start with a dedicated listener for the
|
||||||
// rpc server, we return it directly, and empty server options
|
// rpc server, we return it directly, and empty server options
|
||||||
@ -510,8 +524,8 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// TODO(halseth): any point in adding TLS support for custom
|
// TODO(halseth): any point in adding TLS support for custom
|
||||||
// listeners?
|
// listeners?
|
||||||
if lisCfg.RPCListener != nil {
|
if lisCfg.RPCListener != nil {
|
||||||
return []net.Listener{lisCfg.RPCListener}, func() {},
|
return []*ListenerWithSignal{lisCfg.RPCListener},
|
||||||
[]grpc.ServerOption{}, nil
|
func() {}, []grpc.ServerOption{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we'll return the regular listeners.
|
// Otherwise we'll return the regular listeners.
|
||||||
@ -841,9 +855,13 @@ func waitForWalletPassword(restEndpoints []net.Addr,
|
|||||||
|
|
||||||
for _, lis := range listeners {
|
for _, lis := range listeners {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(lis net.Listener) {
|
go func(lis *ListenerWithSignal) {
|
||||||
rpcsLog.Infof("password RPC server listening on %s",
|
rpcsLog.Infof("password RPC server listening on %s",
|
||||||
lis.Addr())
|
lis.Addr())
|
||||||
|
|
||||||
|
// Close the ready chan to indicate we are listening.
|
||||||
|
close(lis.Ready)
|
||||||
|
|
||||||
wg.Done()
|
wg.Done()
|
||||||
grpcServer.Serve(lis)
|
grpcServer.Serve(lis)
|
||||||
}(lis)
|
}(lis)
|
||||||
|
@ -16,7 +16,11 @@ import (
|
|||||||
// extraArgs can be used to pass command line arguments to lnd that will
|
// extraArgs can be used to pass command line arguments to lnd that will
|
||||||
// override what is found in the config file. Example:
|
// override what is found in the config file. Example:
|
||||||
// extraArgs = "--bitcoin.testnet --lnddir=\"/tmp/folder name/\" --profile=5050"
|
// extraArgs = "--bitcoin.testnet --lnddir=\"/tmp/folder name/\" --profile=5050"
|
||||||
func Start(extraArgs string, callback Callback) {
|
//
|
||||||
|
// The unlockerReady callback is called when the WalletUnlocker service is
|
||||||
|
// ready, and rpcReady is called after the wallet has been unlocked and lnd is
|
||||||
|
// ready to accept RPC calls.
|
||||||
|
func Start(extraArgs string, unlockerReady, rpcReady Callback) {
|
||||||
// Split the argument string on "--" to get separated command line
|
// Split the argument string on "--" to get separated command line
|
||||||
// arguments.
|
// arguments.
|
||||||
var splitArgs []string
|
var splitArgs []string
|
||||||
@ -33,11 +37,24 @@ func Start(extraArgs string, callback Callback) {
|
|||||||
// startup.
|
// startup.
|
||||||
os.Args = append(os.Args, splitArgs...)
|
os.Args = append(os.Args, splitArgs...)
|
||||||
|
|
||||||
|
// Set up channels that will be notified when the RPC servers are ready
|
||||||
|
// to accept calls.
|
||||||
|
var (
|
||||||
|
unlockerListening = make(chan struct{})
|
||||||
|
rpcListening = make(chan struct{})
|
||||||
|
)
|
||||||
|
|
||||||
// We call the main method with the custom in-memory listeners called
|
// We call the main method with the custom in-memory listeners called
|
||||||
// by the mobile APIs, such that the grpc server will use these.
|
// by the mobile APIs, such that the grpc server will use these.
|
||||||
cfg := lnd.ListenerCfg{
|
cfg := lnd.ListenerCfg{
|
||||||
WalletUnlocker: walletUnlockerLis,
|
WalletUnlocker: &lnd.ListenerWithSignal{
|
||||||
RPCListener: lightningLis,
|
Listener: walletUnlockerLis,
|
||||||
|
Ready: unlockerListening,
|
||||||
|
},
|
||||||
|
RPCListener: &lnd.ListenerWithSignal{
|
||||||
|
Listener: lightningLis,
|
||||||
|
Ready: rpcListening,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the "real" main in a nested manner so the defers will properly
|
// Call the "real" main in a nested manner so the defers will properly
|
||||||
@ -53,9 +70,15 @@ func Start(extraArgs string, callback Callback) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// TODO(halseth): callback when RPC server is actually running. Since
|
// Finally we start two go routines that will call the provided
|
||||||
// the RPC server might take a while to start up, the client might
|
// callbacks when the RPC servers are ready to accept calls.
|
||||||
// assume it is ready to accept calls when this callback is sent, while
|
go func() {
|
||||||
// it's not.
|
<-unlockerListening
|
||||||
callback.OnResponse([]byte("started"))
|
unlockerReady.OnResponse([]byte{})
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-rpcListening
|
||||||
|
rpcReady.OnResponse([]byte{})
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -461,7 +460,7 @@ type rpcServer struct {
|
|||||||
// listeners is a list of listeners to use when starting the grpc
|
// listeners is a list of listeners to use when starting the grpc
|
||||||
// server. We make it configurable such that the grpc server can listen
|
// server. We make it configurable such that the grpc server can listen
|
||||||
// on custom interfaces.
|
// on custom interfaces.
|
||||||
listeners []net.Listener
|
listeners []*ListenerWithSignal
|
||||||
|
|
||||||
// listenerCleanUp are a set of closures functions that will allow this
|
// listenerCleanUp are a set of closures functions that will allow this
|
||||||
// main RPC server to clean up all the listening socket created for the
|
// main RPC server to clean up all the listening socket created for the
|
||||||
@ -715,8 +714,11 @@ func (r *rpcServer) Start() error {
|
|||||||
// With all the sub-servers started, we'll spin up the listeners for
|
// With all the sub-servers started, we'll spin up the listeners for
|
||||||
// the main RPC server itself.
|
// the main RPC server itself.
|
||||||
for _, lis := range r.listeners {
|
for _, lis := range r.listeners {
|
||||||
go func(lis net.Listener) {
|
go func(lis *ListenerWithSignal) {
|
||||||
rpcsLog.Infof("RPC server listening on %s", lis.Addr())
|
rpcsLog.Infof("RPC server listening on %s", lis.Addr())
|
||||||
|
|
||||||
|
// Close the ready chan to indicate we are listening.
|
||||||
|
close(lis.Ready)
|
||||||
r.grpcServer.Serve(lis)
|
r.grpcServer.Serve(lis)
|
||||||
}(lis)
|
}(lis)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user