• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 14358372723

09 Apr 2025 01:26PM UTC coverage: 56.696% (-12.3%) from 69.037%
14358372723

Pull #9696

github

web-flow
Merge e2837e400 into 867d27d68
Pull Request #9696: Add `development_guidelines.md` for both human and machine

107055 of 188823 relevant lines covered (56.7%)

22721.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

28.57
/lnrpc/sub_server.go
1
package lnrpc
2

3
import (
4
        "context"
5
        "fmt"
6
        "sync"
7

8
        "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
9
        "google.golang.org/grpc"
10
        "gopkg.in/macaroon-bakery.v2/bakery"
11
)
12

13
// MacaroonPerms is a map from the FullMethod of an invoked gRPC command. It
14
// maps the set of operations that the macaroon presented with the command MUST
15
// satisfy. With this map, all sub-servers are able to communicate to the
16
// primary macaroon service what type of macaroon must be passed with each
17
// method present on the service of the sub-server.
18
type MacaroonPerms map[string][]bakery.Op
19

20
// SubServer is a child server of the main lnrpc gRPC server. Sub-servers allow
21
// lnd to expose discrete services that can be used with or independent of the
22
// main RPC server. The main rpcserver will create, start, stop, and manage
23
// each sub-server in a generalized manner.
24
type SubServer interface {
25
        // Start starts the sub-server and all goroutines it needs to operate.
26
        Start() error
27

28
        // Stop signals that the sub-server should wrap up any lingering
29
        // requests, and being a graceful shutdown.
30
        Stop() error
31

32
        // Name returns a unique string representation of the sub-server. This
33
        // can be used to identify the sub-server and also de-duplicate them.
34
        Name() string
35
}
36

37
// GrpcHandler is the interface that should be registered with the root gRPC
38
// server, and is the interface that implements the subserver's defined RPC.
39
// Before the actual sub server has been created, this will be an empty shell
40
// allowing us to start the gRPC server before we have all the dependencies
41
// needed to create the subserver itself.
42
type GrpcHandler interface {
43
        // RegisterWithRootServer will be called by the root gRPC server to
44
        // direct a sub RPC server to register itself with the main gRPC root
45
        // server. Until this is called, each sub-server won't be able to have
46
        // requests routed towards it.
47
        RegisterWithRootServer(*grpc.Server) error
48

49
        // RegisterWithRestServer will be called by the root REST mux to direct
50
        // a sub RPC server to register itself with the main REST mux server.
51
        // Until this is called, each sub-server won't be able to have requests
52
        // routed towards it.
53
        RegisterWithRestServer(context.Context, *runtime.ServeMux, string,
54
                []grpc.DialOption) error
55

56
        // CreateSubServer populates the subserver's dependencies using the
57
        // passed SubServerConfigDispatcher. This method should fully
58
        // initialize the sub-server instance, making it ready for action. It
59
        // returns the macaroon permissions that the sub-server wishes to pass
60
        // on to the root server for all methods routed towards it.
61
        CreateSubServer(subCfgs SubServerConfigDispatcher) (SubServer,
62
                MacaroonPerms, error)
63
}
64

65
// SubServerConfigDispatcher is an interface that all sub-servers will use to
66
// dynamically locate their configuration files. This abstraction will allow
67
// the primary RPC sever to initialize all sub-servers in a generic manner
68
// without knowing of each individual sub server.
69
type SubServerConfigDispatcher interface {
70
        // FetchConfig attempts to locate an existing configuration file mapped
71
        // to the target sub-server. If we're unable to find a config file
72
        // matching the subServerName name, then false will be returned for the
73
        // second parameter.
74
        FetchConfig(subServerName string) (interface{}, bool)
75
}
76

77
// SubServerDriver is a template struct that allows the root server to create a
78
// sub-server gRPC handler with minimal knowledge.
79
type SubServerDriver struct {
80
        // SubServerName is the full name of a sub-sever.
81
        //
82
        // NOTE: This MUST be unique.
83
        SubServerName string
84

85
        // NewGrpcHandler creates a a new sub-server gRPC interface that can be
86
        // registered with the root gRPC server. It is not expected that the
87
        // SubServer is ready for operation before its CreateSubServer and
88
        // Start methods have been called.
89
        NewGrpcHandler func() GrpcHandler
90
}
91

92
var (
93
        // subServers is a package level global variable that houses all the
94
        // registered sub-servers.
95
        subServers = make(map[string]*SubServerDriver)
96

97
        // registerMtx is a mutex that protects access to the above subServer
98
        // map.
99
        registerMtx sync.Mutex
100
)
101

102
// RegisteredSubServers returns all registered sub-servers.
103
//
104
// NOTE: This function is safe for concurrent access.
105
func RegisteredSubServers() []*SubServerDriver {
×
106
        registerMtx.Lock()
×
107
        defer registerMtx.Unlock()
×
108

×
109
        drivers := make([]*SubServerDriver, 0, len(subServers))
×
110
        for _, driver := range subServers {
×
111
                drivers = append(drivers, driver)
×
112
        }
×
113

114
        return drivers
×
115
}
116

117
// RegisterSubServer should be called by a sub-server within its package's
118
// init() method to register its existence with the main sub-server map. Each
119
// sub-server, if active, is meant to register via this method in their init()
120
// method. This allows callers to easily initialize and register all
121
// sub-servers without knowing any details beyond that the fact that they
122
// satisfy the necessary interfaces.
123
//
124
// NOTE: This function is safe for concurrent access.
125
func RegisterSubServer(driver *SubServerDriver) error {
13✔
126
        registerMtx.Lock()
13✔
127
        defer registerMtx.Unlock()
13✔
128

13✔
129
        if _, ok := subServers[driver.SubServerName]; ok {
13✔
130
                return fmt.Errorf("subserver already registered")
×
131
        }
×
132

133
        subServers[driver.SubServerName] = driver
13✔
134

13✔
135
        return nil
13✔
136
}
137

138
// SupportedServers returns slice of the names of all registered sub-servers.
139
//
140
// NOTE: This function is safe for concurrent access.
141
func SupportedServers() []string {
×
142
        registerMtx.Lock()
×
143
        defer registerMtx.Unlock()
×
144

×
145
        supportedSubServers := make([]string, 0, len(subServers))
×
146
        for driverName := range subServers {
×
147
                supportedSubServers = append(supportedSubServers, driverName)
×
148
        }
×
149

150
        return supportedSubServers
×
151
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc