@@ -15,6 +15,7 @@ import (
15
15
"github.com/lightninglabs/lightning-terminal/litrpc"
16
16
"github.com/lightninglabs/lightning-terminal/perms"
17
17
"github.com/lightninglabs/lightning-terminal/session"
18
+ litstatus "github.com/lightninglabs/lightning-terminal/status"
18
19
"github.com/lightninglabs/lightning-terminal/subservers"
19
20
"github.com/lightningnetwork/lnd/lncfg"
20
21
"github.com/lightningnetwork/lnd/macaroons"
@@ -67,7 +68,8 @@ func (e *proxyErr) Unwrap() error {
67
68
// component.
68
69
func newRpcProxy (cfg * Config , validator macaroons.MacaroonValidator ,
69
70
superMacValidator session.SuperMacaroonValidator ,
70
- permsMgr * perms.Manager , subServerMgr * subservers.Manager ) * rpcProxy {
71
+ permsMgr * perms.Manager , subServerMgr * subservers.Manager ,
72
+ statusMgr * litstatus.Manager ) * rpcProxy {
71
73
72
74
// The gRPC web calls are protected by HTTP basic auth which is defined
73
75
// by base64(username:password). Because we only have a password, we
@@ -88,6 +90,7 @@ func newRpcProxy(cfg *Config, validator macaroons.MacaroonValidator,
88
90
macValidator : validator ,
89
91
superMacValidator : superMacValidator ,
90
92
subServerMgr : subServerMgr ,
93
+ statusMgr : statusMgr ,
91
94
}
92
95
p .grpcServer = grpc .NewServer (
93
96
// From the grpxProxy doc: This codec is *crucial* to the
@@ -162,6 +165,7 @@ type rpcProxy struct {
162
165
basicAuth string
163
166
permsMgr * perms.Manager
164
167
subServerMgr * subservers.Manager
168
+ statusMgr * litstatus.Manager
165
169
166
170
bakeSuperMac bakeSuperMac
167
171
@@ -333,6 +337,10 @@ func (p *rpcProxy) makeDirector(allowLitRPC bool) func(ctx context.Context,
333
337
}
334
338
}
335
339
340
+ if err := p .checkSubSystemStarted (requestURI ); err != nil {
341
+ return outCtx , nil , err
342
+ }
343
+
336
344
// Direct the call to the correct backend. All gRPC calls end up
337
345
// here since our gRPC server instance doesn't have any handlers
338
346
// registered itself. So all daemon calls that are remote are
@@ -359,12 +367,6 @@ func (p *rpcProxy) makeDirector(allowLitRPC bool) func(ctx context.Context,
359
367
)
360
368
}
361
369
362
- // If the rpcProxy has not started yet, then the lnd connection
363
- // will not be initialised yet.
364
- if ! p .hasStarted () {
365
- return outCtx , nil , ErrWaitingToStart
366
- }
367
-
368
370
return outCtx , p .lndConn , nil
369
371
}
370
372
}
@@ -375,15 +377,15 @@ func (p *rpcProxy) UnaryServerInterceptor(ctx context.Context, req interface{},
375
377
info * grpc.UnaryServerInfo , handler grpc.UnaryHandler ) (interface {},
376
378
error ) {
377
379
378
- if ! p .hasStarted () && ! isStatusReq (info .FullMethod ) {
379
- return nil , ErrWaitingToStart
380
- }
381
-
382
380
uriPermissions , ok := p .permsMgr .URIPermissions (info .FullMethod )
383
381
if ! ok {
384
382
return nil , ErrUnknownRequest
385
383
}
386
384
385
+ if err := p .checkSubSystemStarted (info .FullMethod ); err != nil {
386
+ return nil , err
387
+ }
388
+
387
389
// For now, basic authentication is just a quick fix until we
388
390
// have proper macaroon support implemented in the UI. We allow
389
391
// gRPC web requests to have it and "convert" the auth into a
@@ -419,15 +421,15 @@ func (p *rpcProxy) StreamServerInterceptor(srv interface{},
419
421
ss grpc.ServerStream , info * grpc.StreamServerInfo ,
420
422
handler grpc.StreamHandler ) error {
421
423
422
- if ! p .hasStarted () && ! isStatusReq (info .FullMethod ) {
423
- return ErrWaitingToStart
424
- }
425
-
426
424
uriPermissions , ok := p .permsMgr .URIPermissions (info .FullMethod )
427
425
if ! ok {
428
426
return ErrUnknownRequest
429
427
}
430
428
429
+ if err := p .checkSubSystemStarted (info .FullMethod ); err != nil {
430
+ return err
431
+ }
432
+
431
433
// For now, basic authentication is just a quick fix until we
432
434
// have proper macaroon support implemented in the UI. We allow
433
435
// gRPC web requests to have it and "convert" the auth into a
@@ -604,6 +606,53 @@ func (p *rpcProxy) convertSuperMacaroon(ctx context.Context, macHex string,
604
606
return nil , nil
605
607
}
606
608
609
+ // checkSubSystemStarted checks if the subsystem responsible for handling the
610
+ // given URI has started.
611
+ func (p * rpcProxy ) checkSubSystemStarted (requestURI string ) error {
612
+ // A request to Lit's status server is always allowed.
613
+ if isStatusReq (requestURI ) {
614
+ return nil
615
+ }
616
+
617
+ // Check if the rpcProxy has started yet.
618
+ if ! p .hasStarted () {
619
+ return ErrWaitingToStart
620
+ }
621
+
622
+ // Currently, Lit and LND are not registered with the sub-server
623
+ // manager, so we let any request for them through.
624
+ if p .permsMgr .IsSubServerURI (subservers .LIT , requestURI ) ||
625
+ p .permsMgr .IsSubServerURI (subservers .LND , requestURI ) {
626
+
627
+ return nil
628
+ }
629
+
630
+ // Check that the sub-server manager does have a sub-server registered
631
+ // that can handle the given URI.
632
+ handled , system := p .subServerMgr .Handles (requestURI )
633
+ if ! handled {
634
+ return fmt .Errorf ("unknown gRPC web request: %v" , requestURI )
635
+ }
636
+
637
+ // Check with the status manger to see if the sub-server is ready to
638
+ // handle the request.
639
+ serverStatus , err := p .statusMgr .GetStatus (system )
640
+ if err != nil {
641
+ return err
642
+ }
643
+
644
+ if serverStatus .Disabled {
645
+ return fmt .Errorf ("%s has been disabled" , system )
646
+ }
647
+
648
+ if ! serverStatus .Running {
649
+ return fmt .Errorf ("%s is not running: %s" , system ,
650
+ serverStatus .Err )
651
+ }
652
+
653
+ return nil
654
+ }
655
+
607
656
// readMacaroon tries to read the macaroon file at the specified path and create
608
657
// gRPC dial options from it.
609
658
func readMacaroon (macPath string ) ([]byte , error ) {
0 commit comments