@@ -50,6 +50,8 @@ type mobileClient struct {
50
50
localPrivCreateCallback NativeCallback
51
51
remoteKeyReceiveCallback NativeCallback
52
52
authDataCallback NativeCallback
53
+
54
+ mutex sync.Mutex
53
55
}
54
56
55
57
func newMobileClient () * mobileClient {
91
93
92
94
m = make (map [string ]* mobileClient )
93
95
94
- // mMutex should always be used to guard the m map
96
+ // mMutex should always be used to guard the mutex map.
95
97
mMutex sync.RWMutex
96
98
97
99
registry = make (map [string ]func (context.Context ,
@@ -100,6 +102,20 @@ var (
100
102
interceptorLogsInitialize = false
101
103
)
102
104
105
+ // getClient returns the mobile client for the given namespace or an error if no
106
+ // client exists.
107
+ func getClient (nameSpace string ) (* mobileClient , error ) {
108
+ mMutex .Lock ()
109
+ defer mMutex .Unlock ()
110
+
111
+ mc , ok := m [nameSpace ]
112
+ if ! ok {
113
+ return nil , fmt .Errorf ("unknown namespace: %v" , nameSpace )
114
+ }
115
+
116
+ return mc , nil
117
+ }
118
+
103
119
// InitLNC sets up everything required for LNC to run including
104
120
// signal interceptor, logs, and an instance of the mobile client.
105
121
func InitLNC (nameSpace , debugLevel string ) error {
@@ -173,85 +189,91 @@ func ConnectServer(nameSpace string, mailboxServer string, isDevServer bool,
173
189
}
174
190
}
175
191
176
- mMutex .Lock ()
177
- defer mMutex .Unlock ()
178
-
179
- mc , ok := m [nameSpace ]
180
- if ! ok {
181
- return fmt .Errorf ("unknown namespace: %s" , nameSpace )
182
- }
183
-
184
- statusChecker , lndConnect , err := core .MailboxRPCConnection (
185
- mailboxServer , pairingPhrase , localPriv , remotePub ,
186
- func (key * btcec.PublicKey ) error {
187
- mc .remoteKeyReceiveCallback .SendResult (
188
- hex .EncodeToString (key .SerializeCompressed ()),
189
- )
190
-
191
- return nil
192
- }, func (data []byte ) error {
193
- parts := strings .Split (string (data ), ": " )
194
- if len (parts ) != 2 || parts [0 ] != "Macaroon" {
195
- return fmt .Errorf ("authdata does " +
196
- "not contain a macaroon" )
197
- }
198
-
199
- macBytes , err := hex .DecodeString (parts [1 ])
200
- if err != nil {
201
- return err
202
- }
203
-
204
- mac := & macaroon.Macaroon {}
205
- err = mac .UnmarshalBinary (macBytes )
206
- if err != nil {
207
- return fmt .Errorf ("unable to decode " +
208
- "macaroon: %v" , err )
209
- }
210
-
211
- mc .mac = mac
192
+ // Since the connection function is blocking, we need to spin it off
193
+ // in another goroutine here. See https://pkg.go.dev/syscall/js#FuncOf.
194
+ go func () {
195
+ mc , err := getClient (nameSpace )
196
+ if err != nil {
197
+ log .Errorf ("Error getting client: %v" , err )
198
+ return
199
+ }
212
200
213
- mc .authDataCallback .SendResult (string (data ))
201
+ mc .mutex .Lock ()
202
+ defer mc .mutex .Unlock ()
203
+
204
+ statusChecker , lndConnect , err := core .MailboxRPCConnection (
205
+ mailboxServer , pairingPhrase , localPriv , remotePub ,
206
+ func (key * btcec.PublicKey ) error {
207
+ mc .remoteKeyReceiveCallback .SendResult (
208
+ hex .EncodeToString (key .SerializeCompressed ()),
209
+ )
210
+
211
+ return nil
212
+ }, func (data []byte ) error {
213
+ parts := strings .Split (string (data ), ": " )
214
+ if len (parts ) != 2 || parts [0 ] != "Macaroon" {
215
+ return fmt .Errorf ("authdata does " +
216
+ "not contain a macaroon" )
217
+ }
218
+
219
+ macBytes , err := hex .DecodeString (parts [1 ])
220
+ if err != nil {
221
+ return err
222
+ }
223
+
224
+ mac := & macaroon.Macaroon {}
225
+ err = mac .UnmarshalBinary (macBytes )
226
+ if err != nil {
227
+ return fmt .Errorf ("unable to decode " +
228
+ "macaroon: %v" , err )
229
+ }
230
+
231
+ mc .mac = mac
232
+
233
+ mc .authDataCallback .SendResult (string (data ))
234
+
235
+ return nil
236
+ },
237
+ )
238
+ if err != nil {
239
+ log .Errorf ("Error running wasm client: %v" , err )
240
+ }
214
241
215
- return nil
216
- },
217
- )
218
- if err != nil {
219
- return err
220
- }
242
+ mc .statusChecker = statusChecker
243
+ mc .lndConn , err = lndConnect ()
244
+ if err != nil {
245
+ log .Errorf ("Error running wasm client: %v" , err )
246
+ }
221
247
222
- mc .statusChecker = statusChecker
223
- mc .lndConn , err = lndConnect ()
224
- if err != nil {
225
- return err
226
- }
248
+ log .Debugf ("Mobile client connected to RPC" )
249
+ }()
227
250
228
- log .Debugf ("Mobile client connected to RPC" )
229
251
return nil
230
252
}
231
253
232
254
// IsConnected returns whether or not there is an active connection.
233
255
func IsConnected (nameSpace string ) (bool , error ) {
234
- mMutex .Lock ()
235
- defer mMutex .Unlock ()
236
-
237
- mc , ok := m [nameSpace ]
238
- if ! ok {
239
- return false , fmt .Errorf ("unknown namespace: %s" , nameSpace )
256
+ mc , err := getClient (nameSpace )
257
+ if err != nil {
258
+ return false , fmt .Errorf ("error getting client: %v" , err )
240
259
}
241
260
261
+ mc .mutex .Lock ()
262
+ defer mc .mutex .Unlock ()
263
+
242
264
return mc .lndConn != nil , nil
243
265
}
244
266
245
267
// Disconnect closes the RPC connection.
246
268
func Disconnect (nameSpace string ) error {
247
- mMutex .Lock ()
248
- defer mMutex .Unlock ()
249
-
250
- mc , ok := m [nameSpace ]
251
- if ! ok {
252
- return fmt .Errorf ("unknown namespace: %s" , nameSpace )
269
+ mc , err := getClient (nameSpace )
270
+ if err != nil {
271
+ return fmt .Errorf ("error getting client: %v" , err )
253
272
}
254
273
274
+ mc .mutex .Lock ()
275
+ defer mc .mutex .Unlock ()
276
+
255
277
if mc .lndConn != nil {
256
278
if err := mc .lndConn .Close (); err != nil {
257
279
log .Errorf ("Error closing RPC connection: %v" , err )
@@ -264,14 +286,14 @@ func Disconnect(nameSpace string) error {
264
286
265
287
// Status returns the status of the LNC RPC connection.
266
288
func Status (nameSpace string ) (string , error ) {
267
- mMutex .Lock ()
268
- defer mMutex .Unlock ()
269
-
270
- mc , ok := m [nameSpace ]
271
- if ! ok {
272
- return "" , fmt .Errorf ("unknown namespace: %s" , nameSpace )
289
+ mc , err := getClient (nameSpace )
290
+ if err != nil {
291
+ return "" , fmt .Errorf ("error getting client: %v" , err )
273
292
}
274
293
294
+ mc .mutex .Lock ()
295
+ defer mc .mutex .Unlock ()
296
+
275
297
if mc .statusChecker == nil {
276
298
return "" , nil
277
299
}
@@ -284,14 +306,14 @@ func Status(nameSpace string) (string, error) {
284
306
func RegisterLocalPrivCreateCallback (nameSpace string ,
285
307
c NativeCallback ) error {
286
308
287
- mMutex .Lock ()
288
- defer mMutex .Unlock ()
289
-
290
- mc , ok := m [nameSpace ]
291
- if ! ok {
292
- return fmt .Errorf ("unknown namespace: %s" , nameSpace )
309
+ mc , err := getClient (nameSpace )
310
+ if err != nil {
311
+ return fmt .Errorf ("error getting client: %v" , err )
293
312
}
294
313
314
+ mc .mutex .Lock ()
315
+ defer mc .mutex .Unlock ()
316
+
295
317
mc .localPrivCreateCallback = c
296
318
297
319
return nil
@@ -302,14 +324,14 @@ func RegisterLocalPrivCreateCallback(nameSpace string,
302
324
func RegisterRemoteKeyReceiveCallback (nameSpace string ,
303
325
c NativeCallback ) error {
304
326
305
- mMutex .Lock ()
306
- defer mMutex .Unlock ()
307
-
308
- mc , ok := m [nameSpace ]
309
- if ! ok {
310
- return fmt .Errorf ("unknown namespace: %s" , nameSpace )
327
+ mc , err := getClient (nameSpace )
328
+ if err != nil {
329
+ return fmt .Errorf ("error getting client: %v" , err )
311
330
}
312
331
332
+ mc .mutex .Lock ()
333
+ defer mc .mutex .Unlock ()
334
+
313
335
mc .remoteKeyReceiveCallback = c
314
336
315
337
return nil
@@ -318,14 +340,14 @@ func RegisterRemoteKeyReceiveCallback(nameSpace string,
318
340
// RegisterAuthDataCallback sets up the native callbacks upon
319
341
// receiving auth data.
320
342
func RegisterAuthDataCallback (nameSpace string , c NativeCallback ) error {
321
- mMutex .Lock ()
322
- defer mMutex .Unlock ()
323
-
324
- mc , ok := m [nameSpace ]
325
- if ! ok {
326
- return fmt .Errorf ("unknown namespace: %s" , nameSpace )
343
+ mc , err := getClient (nameSpace )
344
+ if err != nil {
345
+ return fmt .Errorf ("error getting client: %v" , err )
327
346
}
328
347
348
+ mc .mutex .Lock ()
349
+ defer mc .mutex .Unlock ()
350
+
329
351
mc .authDataCallback = c
330
352
331
353
return nil
@@ -335,14 +357,14 @@ func RegisterAuthDataCallback(nameSpace string, c NativeCallback) error {
335
357
func InvokeRPC (nameSpace string , rpcName string , requestJSON string ,
336
358
c NativeCallback ) error {
337
359
338
- mMutex .Lock ()
339
- defer mMutex .Unlock ()
340
-
341
- mc , ok := m [nameSpace ]
342
- if ! ok {
343
- return fmt .Errorf ("unknown namespace: %s" , nameSpace )
360
+ mc , err := getClient (nameSpace )
361
+ if err != nil {
362
+ return fmt .Errorf ("error getting client: %v" , err )
344
363
}
345
364
365
+ mc .mutex .Lock ()
366
+ defer mc .mutex .Unlock ()
367
+
346
368
if rpcName == "" {
347
369
return fmt .Errorf ("param rpcName required" )
348
370
}
@@ -380,14 +402,14 @@ func InvokeRPC(nameSpace string, rpcName string, requestJSON string,
380
402
381
403
// GetExpiry returns the expiration time of the connection macaroon.
382
404
func GetExpiry (nameSpace string ) (string , error ) {
383
- mMutex .Lock ()
384
- defer mMutex .Unlock ()
385
-
386
- mc , ok := m [nameSpace ]
387
- if ! ok {
388
- return "" , fmt .Errorf ("unknown namespace: %s" , nameSpace )
405
+ mc , err := getClient (nameSpace )
406
+ if err != nil {
407
+ return "" , fmt .Errorf ("error getting client: %v" , err )
389
408
}
390
409
410
+ mc .mutex .Lock ()
411
+ defer mc .mutex .Unlock ()
412
+
391
413
if mc .mac == nil {
392
414
return "" , fmt .Errorf ("macaroon not obtained yet. GetExpiry" +
393
415
"should only be called once the connection is" +
@@ -404,14 +426,14 @@ func GetExpiry(nameSpace string) (string, error) {
404
426
405
427
// IsReadOnly returns whether or not the connection macaroon is read-only.
406
428
func IsReadOnly (nameSpace string ) (bool , error ) {
407
- mMutex .Lock ()
408
- defer mMutex .Unlock ()
409
-
410
- mc , ok := m [nameSpace ]
411
- if ! ok {
412
- return false , fmt .Errorf ("unknown namespace: %s" , nameSpace )
429
+ mc , err := getClient (nameSpace )
430
+ if err != nil {
431
+ return false , fmt .Errorf ("error getting client: %v" , err )
413
432
}
414
433
434
+ mc .mutex .Lock ()
435
+ defer mc .mutex .Unlock ()
436
+
415
437
if mc .mac == nil {
416
438
log .Errorf ("macaroon not obtained yet. IsReadOnly should " +
417
439
"only be called once the connection is complete" )
@@ -430,16 +452,16 @@ func IsReadOnly(nameSpace string) (bool, error) {
430
452
}
431
453
432
454
// HasPermissions returns whether or not the connection macaroon
433
- // has a specificed permission.
455
+ // has a specified permission.
434
456
func HasPermissions (nameSpace , permission string ) (bool , error ) {
435
- mMutex .Lock ()
436
- defer mMutex .Unlock ()
437
-
438
- mc , ok := m [nameSpace ]
439
- if ! ok {
440
- return false , fmt .Errorf ("unknown namespace: %s" , nameSpace )
457
+ mc , err := getClient (nameSpace )
458
+ if err != nil {
459
+ return false , fmt .Errorf ("error getting client: %v" , err )
441
460
}
442
461
462
+ mc .mutex .Lock ()
463
+ defer mc .mutex .Unlock ()
464
+
443
465
if permission == "" {
444
466
return false , nil
445
467
}
@@ -553,17 +575,17 @@ func validateArgs(mailboxServer, localPrivKey, remotePubKey string) error {
553
575
// parseKeys parses the given keys from their string format and calls callback
554
576
// functions where appropriate. NOTE: This function assumes that the parameter
555
577
// combinations have been checked by validateArgs.
556
- func parseKeys (nameSpace , localPrivKey , remotePubKey string ) (
557
- keychain.SingleKeyECDH , * btcec.PublicKey , error ) {
578
+ func parseKeys (nameSpace , localPrivKey ,
579
+ remotePubKey string ) ( keychain.SingleKeyECDH , * btcec.PublicKey , error ) {
558
580
559
- mMutex .Lock ()
560
- defer mMutex .Unlock ()
561
-
562
- mc , ok := m [nameSpace ]
563
- if ! ok {
564
- return nil , nil , fmt .Errorf ("unknown namespace: %s" , nameSpace )
581
+ mc , err := getClient (nameSpace )
582
+ if err != nil {
583
+ return nil , nil , fmt .Errorf ("error getting client: %v" , err )
565
584
}
566
585
586
+ mc .mutex .Lock ()
587
+ defer mc .mutex .Unlock ()
588
+
567
589
var (
568
590
localStaticKey keychain.SingleKeyECDH
569
591
remoteStaticKey * btcec.PublicKey
0 commit comments