Skip to content

Commit 028fec4

Browse files
committed
mobile: add support for multiple LNC connections
1 parent b8b4329 commit 028fec4

File tree

1 file changed

+68
-59
lines changed

1 file changed

+68
-59
lines changed

mobile/mobile.go

Lines changed: 68 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ type mobileClient struct {
4545

4646
registry map[string]func(context.Context, *grpc.ClientConn,
4747
string, func(string, error))
48+
49+
localPrivCreateCallback NativeCallback
50+
remoteKeyReceiveCallback NativeCallback
51+
authDataCallback NativeCallback
4852
}
4953

5054
func newMobileClient() *mobileClient {
@@ -84,51 +88,54 @@ var (
8488

8589
jsonCBRegex = regexp.MustCompile(`(\w+)\.(\w+)\.(\w+)`)
8690

87-
m *mobileClient
91+
m = make(map[string]*mobileClient)
8892

8993
registry = make(map[string]func(context.Context,
9094
*grpc.ClientConn, string, func(string, error)))
9195

92-
localPrivCreateCallback NativeCallback
93-
remoteKeyReceiveCallback NativeCallback
94-
authDataCallback NativeCallback
96+
interceptorLogsInitialize = false
9597
)
9698

9799
// InitLNC sets up everything required for LNC to run including
98100
// signal interceptor, logs, and an instance of the mobile client.
99-
func InitLNC(debugLevel string) error {
100-
// set debug level to 'info' if not specified
101-
if debugLevel == "" {
102-
debugLevel = "info"
103-
}
101+
func InitLNC(namespace, debugLevel string) error {
102+
// only initialize interceptor and logs on first connection
103+
if !interceptorLogsInitialize {
104+
// set debug level to 'info' if not specified
105+
if debugLevel == "" {
106+
debugLevel = "info"
107+
}
104108

105-
// Hook interceptor for os signals.
106-
shutdownInterceptor, err := signal.Intercept()
107-
if err != nil {
108-
return err
109-
}
109+
// Hook interceptor for os signals.
110+
shutdownInterceptor, err := signal.Intercept()
111+
if err != nil {
112+
return err
113+
}
110114

111-
logWriter := build.NewRotatingLogWriter()
112-
SetupLoggers(logWriter, shutdownInterceptor)
115+
logWriter := build.NewRotatingLogWriter()
116+
SetupLoggers(logWriter, shutdownInterceptor)
113117

114-
err = build.ParseAndSetDebugLevels(debugLevel, logWriter)
115-
if err != nil {
116-
return err
117-
}
118+
err = build.ParseAndSetDebugLevels(debugLevel, logWriter)
119+
if err != nil {
120+
return err
121+
}
118122

119-
m = newMobileClient()
123+
for _, registration := range registrations {
124+
registration(registry)
125+
}
120126

121-
for _, registration := range registrations {
122-
registration(registry)
127+
interceptorLogsInitialize = true
123128
}
124129

130+
m[namespace] = newMobileClient()
131+
125132
log.Debugf("Mobile client ready for connecting")
126133
return nil
127134
}
128135

129136
// ConnectServer creates a connection from the client to the
130137
// mailbox server.
131-
func ConnectServer(mailboxServer string, isDevServer bool,
138+
func ConnectServer(namespace string, mailboxServer string, isDevServer bool,
132139
pairingPhrase string, localStatic string, remoteStatic string) error {
133140

134141
// Check that the correct arguments and config combinations have been
@@ -139,7 +146,7 @@ func ConnectServer(mailboxServer string, isDevServer bool,
139146
}
140147

141148
// Parse the key arguments.
142-
localPriv, remotePub, err := parseKeys(localStatic, remoteStatic)
149+
localPriv, remotePub, err := parseKeys(namespace, localStatic, remoteStatic)
143150
if err != nil {
144151
return err
145152
}
@@ -156,7 +163,7 @@ func ConnectServer(mailboxServer string, isDevServer bool,
156163
statusChecker, lndConnect, err := core.MailboxRPCConnection(
157164
mailboxServer, pairingPhrase, localPriv, remotePub,
158165
func(key *btcec.PublicKey) error {
159-
remoteKeyReceiveCallback.SendResult(hex.EncodeToString(
166+
m[namespace].remoteKeyReceiveCallback.SendResult(hex.EncodeToString(
160167
key.SerializeCompressed(),
161168
))
162169

@@ -180,9 +187,9 @@ func ConnectServer(mailboxServer string, isDevServer bool,
180187
"macaroon: %v", err)
181188
}
182189

183-
m.mac = mac
190+
m[namespace].mac = mac
184191

185-
authDataCallback.SendResult(string(data))
192+
m[namespace].authDataCallback.SendResult(string(data))
186193

187194
return nil
188195
},
@@ -192,8 +199,8 @@ func ConnectServer(mailboxServer string, isDevServer bool,
192199
return err
193200
}
194201

195-
m.statusChecker = statusChecker
196-
m.lndConn, err = lndConnect()
202+
m[namespace].statusChecker = statusChecker
203+
m[namespace].lndConn, err = lndConnect()
197204
if err != nil {
198205
return err
199206
}
@@ -203,49 +210,51 @@ func ConnectServer(mailboxServer string, isDevServer bool,
203210
}
204211

205212
// IsConnected returns whether or not there is an active connection.
206-
func IsConnected() bool {
207-
return m.lndConn != nil
213+
func IsConnected(namespace string) bool {
214+
return m[namespace].lndConn != nil
208215
}
209216

210217
// Disconnect closes the RPC connection.
211-
func Disconnect() {
212-
if m.lndConn != nil {
213-
if err := m.lndConn.Close(); err != nil {
218+
func Disconnect(namespace string) {
219+
if m[namespace].lndConn != nil {
220+
if err := m[namespace].lndConn.Close(); err != nil {
214221
log.Errorf("Error closing RPC connection: %v", err)
215222
}
216-
m.lndConn = nil
223+
m[namespace].lndConn = nil
217224
}
218225
}
219226

220227
// Status returns the status of the LNC RPC connection.
221-
func Status() string {
222-
if m.statusChecker == nil {
228+
func Status(namespace string) string {
229+
if m[namespace].statusChecker == nil {
223230
return ""
224231
}
225232

226-
return m.statusChecker().String()
233+
return m[namespace].statusChecker().String()
227234
}
228235

229236
// RegisterLocalPrivCreateCallback sets up the native callbacks upon
230237
// creation of local private key.
231-
func RegisterLocalPrivCreateCallback(c NativeCallback) {
232-
localPrivCreateCallback = c
238+
func RegisterLocalPrivCreateCallback(namespace string, c NativeCallback) {
239+
m[namespace].localPrivCreateCallback = c
233240
}
234241

235242
// RegisterRemoteKeyReceiveCallback sets up the native callbacks upon
236243
// receiving the remote key from the server.
237-
func RegisterRemoteKeyReceiveCallback(c NativeCallback) {
238-
remoteKeyReceiveCallback = c
244+
func RegisterRemoteKeyReceiveCallback(namespace string, c NativeCallback) {
245+
m[namespace].remoteKeyReceiveCallback = c
239246
}
240247

241248
// RegisterAuthDataCallback sets up the native callbacks upon
242249
// receiving auth data.
243-
func RegisterAuthDataCallback(c NativeCallback) {
244-
authDataCallback = c
250+
func RegisterAuthDataCallback(namespace string, c NativeCallback) {
251+
m[namespace].authDataCallback = c
245252
}
246253

247254
// InvokeRPC makes a synchronous RPC call.
248-
func InvokeRPC(rpcName string, requestJSON string, c NativeCallback) error {
255+
func InvokeRPC(namespace string, rpcName string, requestJSON string,
256+
c NativeCallback) error {
257+
249258
if rpcName == "" {
250259
return fmt.Errorf("param rpcName required")
251260
}
@@ -254,7 +263,7 @@ func InvokeRPC(rpcName string, requestJSON string, c NativeCallback) error {
254263
return fmt.Errorf("param requestJSON required")
255264
}
256265

257-
if m.lndConn == nil {
266+
if m[namespace].lndConn == nil {
258267
return fmt.Errorf("RPC connection not ready")
259268
}
260269

@@ -273,21 +282,21 @@ func InvokeRPC(rpcName string, requestJSON string, c NativeCallback) error {
273282
}
274283
}
275284
ctx := context.Background()
276-
method(ctx, m.lndConn, requestJSON, cb)
285+
method(ctx, m[namespace].lndConn, requestJSON, cb)
277286
<-ctx.Done()
278287
}()
279288

280289
return nil
281290
}
282291

283292
// GetExpiry returns the expiration time of the connection macaroon.
284-
func GetExpiry() (string, error) {
285-
if m.mac == nil {
293+
func GetExpiry(namespace string) (string, error) {
294+
if m[namespace].mac == nil {
286295
return "", fmt.Errorf("macaroon not obtained yet. GetExpiry should " +
287296
"only be called once the connection is complete")
288297
}
289298

290-
expiry, found := checkers.ExpiryTime(nil, m.mac.Caveats())
299+
expiry, found := checkers.ExpiryTime(nil, m[namespace].mac.Caveats())
291300
if !found {
292301
return "", fmt.Errorf("expiry not found")
293302
}
@@ -296,14 +305,14 @@ func GetExpiry() (string, error) {
296305
}
297306

298307
// IsReadOnly returns whether or not the connection macaroon is read-only.
299-
func IsReadOnly() bool {
300-
if m.mac == nil {
308+
func IsReadOnly(namespace string) bool {
309+
if m[namespace].mac == nil {
301310
log.Errorf("macaroon not obtained yet. IsReadOnly should " +
302311
"only be called once the connection is complete")
303312
return false
304313
}
305314

306-
macOps, err := extractMacaroonOps(m.mac)
315+
macOps, err := extractMacaroonOps(m[namespace].mac)
307316
if err != nil {
308317
log.Errorf("could not extract macaroon ops: %v", err)
309318
return false
@@ -316,12 +325,12 @@ func IsReadOnly() bool {
316325

317326
// HasPermissions returns whether or not the connection macaroon
318327
// has a specificed permission.
319-
func HasPermissions(permission string) bool {
328+
func HasPermissions(namespace, permission string) bool {
320329
if permission == "" {
321330
return false
322331
}
323332

324-
if m.mac == nil {
333+
if m[namespace].mac == nil {
325334
log.Errorf("macaroon not obtained yet. HasPermissions should " +
326335
"only be called once the connection is complete")
327336
return false
@@ -340,7 +349,7 @@ func HasPermissions(permission string) bool {
340349
return false
341350
}
342351

343-
macOps, err := extractMacaroonOps(m.mac)
352+
macOps, err := extractMacaroonOps(m[namespace].mac)
344353
if err != nil {
345354
log.Errorf("could not extract macaroon ops: %v", err)
346355
return false
@@ -430,7 +439,7 @@ func validateArgs(mailboxServer, localPrivKey, remotePubKey string) error {
430439
// parseKeys parses the given keys from their string format and calls callback
431440
// functions where appropriate. NOTE: This function assumes that the parameter
432441
// combinations have been checked by validateArgs.
433-
func parseKeys(localPrivKey, remotePubKey string) (
442+
func parseKeys(namespace, localPrivKey, remotePubKey string) (
434443
keychain.SingleKeyECDH, *btcec.PublicKey, error) {
435444

436445
var (
@@ -449,7 +458,7 @@ func parseKeys(localPrivKey, remotePubKey string) (
449458
}
450459
localStaticKey = &keychain.PrivKeyECDH{PrivKey: privKey}
451460

452-
localPrivCreateCallback.SendResult(
461+
m[namespace].localPrivCreateCallback.SendResult(
453462
hex.EncodeToString(privKey.Serialize()),
454463
)
455464

0 commit comments

Comments
 (0)