@@ -11,6 +11,7 @@ import (
1111 "time"
1212
1313 "github.com/improbable-eng/grpc-web/go/grpcweb"
14+ "github.com/lightningnetwork/lnd/lncfg"
1415 "github.com/lightningnetwork/lnd/macaroons"
1516 grpcProxy "github.com/mwitkow/grpc-proxy/proxy"
1617 "google.golang.org/grpc"
@@ -111,6 +112,9 @@ func newRpcProxy(cfg *Config, validator macaroons.MacaroonValidator,
111112// v authenticated call | - pool |
112113// +---+----------------------+ +--------------------+
113114// | lnd (remote or local) |
115+ // | faraday remote |
116+ // | loop remote |
117+ // | pool remote |
114118// +--------------------------+
115119//
116120type rpcProxy struct {
@@ -119,7 +123,11 @@ type rpcProxy struct {
119123
120124 macValidator macaroons.MacaroonValidator
121125
122- lndConn * grpc.ClientConn
126+ lndConn * grpc.ClientConn
127+ faradayConn * grpc.ClientConn
128+ loopConn * grpc.ClientConn
129+ poolConn * grpc.ClientConn
130+
123131 grpcServer * grpc.Server
124132 grpcWebProxy * grpcweb.WrappedGrpcServer
125133}
@@ -135,6 +143,41 @@ func (p *rpcProxy) Start() error {
135143 return fmt .Errorf ("could not dial lnd: %v" , err )
136144 }
137145
146+ // Make sure we can connect to all the daemons that are configured to be
147+ // running in remote mode.
148+ if p .cfg .faradayRemote {
149+ p .faradayConn , err = dialBackend (
150+ "faraday" , p .cfg .Remote .Faraday .RPCServer ,
151+ lncfg .CleanAndExpandPath (
152+ p .cfg .Remote .Faraday .TLSCertPath ,
153+ ),
154+ )
155+ if err != nil {
156+ return fmt .Errorf ("could not dial remote faraday: %v" ,
157+ err )
158+ }
159+ }
160+
161+ if p .cfg .loopRemote {
162+ p .loopConn , err = dialBackend (
163+ "loop" , p .cfg .Remote .Loop .RPCServer ,
164+ lncfg .CleanAndExpandPath (p .cfg .Remote .Loop .TLSCertPath ),
165+ )
166+ if err != nil {
167+ return fmt .Errorf ("could not dial remote loop: %v" , err )
168+ }
169+ }
170+
171+ if p .cfg .poolRemote {
172+ p .poolConn , err = dialBackend (
173+ "pool" , p .cfg .Remote .Pool .RPCServer ,
174+ lncfg .CleanAndExpandPath (p .cfg .Remote .Pool .TLSCertPath ),
175+ )
176+ if err != nil {
177+ return fmt .Errorf ("could not dial remote pool: %v" , err )
178+ }
179+ }
180+
138181 return nil
139182}
140183
@@ -149,6 +192,27 @@ func (p *rpcProxy) Stop() error {
149192 }
150193 }
151194
195+ if p .faradayConn != nil {
196+ if err := p .faradayConn .Close (); err != nil {
197+ log .Errorf ("Error closing faraday connection: %v" , err )
198+ return err
199+ }
200+ }
201+
202+ if p .loopConn != nil {
203+ if err := p .loopConn .Close (); err != nil {
204+ log .Errorf ("Error closing loop connection: %v" , err )
205+ return err
206+ }
207+ }
208+
209+ if p .poolConn != nil {
210+ if err := p .poolConn .Close (); err != nil {
211+ log .Errorf ("Error closing pool connection: %v" , err )
212+ return err
213+ }
214+ }
215+
152216 return nil
153217}
154218
@@ -188,7 +252,7 @@ func (p *rpcProxy) isHandling(resp http.ResponseWriter,
188252// backend, depending on what kind of authentication information is attached to
189253// the request.
190254func (p * rpcProxy ) director (ctx context.Context ,
191- _ string ) (context.Context , * grpc.ClientConn , error ) {
255+ requestURI string ) (context.Context , * grpc.ClientConn , error ) {
192256
193257 // If this header is present in the request from the web client,
194258 // the actual connection to the backend will not be established.
@@ -199,7 +263,29 @@ func (p *rpcProxy) director(ctx context.Context,
199263
200264 outCtx := metadata .NewOutgoingContext (ctx , mdCopy )
201265
202- return outCtx , p .lndConn , nil
266+ // Direct the call to the correct backend. For lnd we _always_ have a
267+ // client connection, no matter if it's running in integrated or remote
268+ // mode. For all other daemons the request shouldn't get here in
269+ // integrated mode (after all, the director only picks up calls that the
270+ // gRPC server itself would throw a 404 for) so we throw an error
271+ // message for them if they're not in remote mode.
272+ switch {
273+ case isLndURI (requestURI ):
274+ return outCtx , p .lndConn , nil
275+
276+ case isFaradayURI (requestURI ) && p .cfg .faradayRemote :
277+ return outCtx , p .faradayConn , nil
278+
279+ case isLoopURI (requestURI ) && p .cfg .loopRemote :
280+ return outCtx , p .loopConn , nil
281+
282+ case isPoolURI (requestURI ) && p .cfg .poolRemote :
283+ return outCtx , p .poolConn , nil
284+
285+ default :
286+ return ctx , nil , fmt .Errorf ("unknown gRPC web request: %v" ,
287+ requestURI )
288+ }
203289}
204290
205291// UnaryServerInterceptor is a gRPC interceptor that checks whether the
@@ -313,13 +399,25 @@ func (p *rpcProxy) basicAuthToMacaroon(ctx context.Context,
313399 _ , _ , _ , macPath = p .cfg .lndConnectParams ()
314400
315401 case isLoopURI (requestURI ):
316- macPath = p .cfg .Loop .MacaroonPath
402+ if p .cfg .loopRemote {
403+ macPath = p .cfg .Remote .Loop .MacaroonPath
404+ } else {
405+ macPath = p .cfg .Loop .MacaroonPath
406+ }
317407
318408 case isFaradayURI (requestURI ):
319- macPath = p .cfg .Faraday .MacaroonPath
409+ if p .cfg .faradayRemote {
410+ macPath = p .cfg .Remote .Faraday .MacaroonPath
411+ } else {
412+ macPath = p .cfg .Faraday .MacaroonPath
413+ }
320414
321415 case isPoolURI (requestURI ):
322- macPath = p .cfg .Pool .MacaroonPath
416+ if p .cfg .poolRemote {
417+ macPath = p .cfg .Remote .Pool .MacaroonPath
418+ } else {
419+ macPath = p .cfg .Pool .MacaroonPath
420+ }
323421
324422 default :
325423 return ctx , fmt .Errorf ("unknown gRPC web request: %v" ,
@@ -328,7 +426,7 @@ func (p *rpcProxy) basicAuthToMacaroon(ctx context.Context,
328426
329427 // Now that we know which macaroon to load, do it and attach it to the
330428 // request context.
331- macBytes , err := readMacaroon (macPath )
429+ macBytes , err := readMacaroon (lncfg . CleanAndExpandPath ( macPath ) )
332430 if err != nil {
333431 return ctx , fmt .Errorf ("error reading macaroon: %v" , err )
334432 }
0 commit comments