Skip to content

Commit 1d483e8

Browse files
committed
Mobile: locking enhancements
mobile: suggest improvements to locking
1 parent d58e391 commit 1d483e8

File tree

1 file changed

+95
-78
lines changed

1 file changed

+95
-78
lines changed

mobile/mobile.go

Lines changed: 95 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ type mobileClient struct {
5050
localPrivCreateCallback NativeCallback
5151
remoteKeyReceiveCallback NativeCallback
5252
authDataCallback NativeCallback
53+
54+
mutex sync.Mutex
5355
}
5456

5557
func newMobileClient() *mobileClient {
@@ -91,7 +93,7 @@ var (
9193

9294
m = make(map[string]*mobileClient)
9395

94-
// mMutex should always be used to guard the m map
96+
// mMutex should always be used to guard the mutex map.
9597
mMutex sync.RWMutex
9698

9799
registry = make(map[string]func(context.Context,
@@ -100,6 +102,20 @@ var (
100102
interceptorLogsInitialize = false
101103
)
102104

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+
103119
// InitLNC sets up everything required for LNC to run including
104120
// signal interceptor, logs, and an instance of the mobile client.
105121
func InitLNC(nameSpace, debugLevel string) error {
@@ -173,17 +189,18 @@ func ConnectServer(nameSpace string, mailboxServer string, isDevServer bool,
173189
}
174190
}
175191

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-
184192
// Since the connection function is blocking, we need to spin it off
185193
// in another goroutine here. See https://pkg.go.dev/syscall/js#FuncOf.
186194
go func() {
195+
mc, err := getClient(nameSpace)
196+
if err != nil {
197+
log.Errorf("Error getting client: %v", err)
198+
return
199+
}
200+
201+
mc.mutex.Lock()
202+
defer mc.mutex.Unlock()
203+
187204
statusChecker, lndConnect, err := core.MailboxRPCConnection(
188205
mailboxServer, pairingPhrase, localPriv, remotePub,
189206
func(key *btcec.PublicKey) error {
@@ -236,27 +253,27 @@ func ConnectServer(nameSpace string, mailboxServer string, isDevServer bool,
236253

237254
// IsConnected returns whether or not there is an active connection.
238255
func IsConnected(nameSpace string) (bool, error) {
239-
mMutex.Lock()
240-
defer mMutex.Unlock()
241-
242-
mc, ok := m[nameSpace]
243-
if !ok {
244-
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)
245259
}
246260

261+
mc.mutex.Lock()
262+
defer mc.mutex.Unlock()
263+
247264
return mc.lndConn != nil, nil
248265
}
249266

250267
// Disconnect closes the RPC connection.
251268
func Disconnect(nameSpace string) error {
252-
mMutex.Lock()
253-
defer mMutex.Unlock()
254-
255-
mc, ok := m[nameSpace]
256-
if !ok {
257-
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)
258272
}
259273

274+
mc.mutex.Lock()
275+
defer mc.mutex.Unlock()
276+
260277
if mc.lndConn != nil {
261278
if err := mc.lndConn.Close(); err != nil {
262279
log.Errorf("Error closing RPC connection: %v", err)
@@ -269,14 +286,14 @@ func Disconnect(nameSpace string) error {
269286

270287
// Status returns the status of the LNC RPC connection.
271288
func Status(nameSpace string) (string, error) {
272-
mMutex.Lock()
273-
defer mMutex.Unlock()
274-
275-
mc, ok := m[nameSpace]
276-
if !ok {
277-
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)
278292
}
279293

294+
mc.mutex.Lock()
295+
defer mc.mutex.Unlock()
296+
280297
if mc.statusChecker == nil {
281298
return "", nil
282299
}
@@ -289,14 +306,14 @@ func Status(nameSpace string) (string, error) {
289306
func RegisterLocalPrivCreateCallback(nameSpace string,
290307
c NativeCallback) error {
291308

292-
mMutex.Lock()
293-
defer mMutex.Unlock()
294-
295-
mc, ok := m[nameSpace]
296-
if !ok {
297-
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)
298312
}
299313

314+
mc.mutex.Lock()
315+
defer mc.mutex.Unlock()
316+
300317
mc.localPrivCreateCallback = c
301318

302319
return nil
@@ -307,14 +324,14 @@ func RegisterLocalPrivCreateCallback(nameSpace string,
307324
func RegisterRemoteKeyReceiveCallback(nameSpace string,
308325
c NativeCallback) error {
309326

310-
mMutex.Lock()
311-
defer mMutex.Unlock()
312-
313-
mc, ok := m[nameSpace]
314-
if !ok {
315-
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)
316330
}
317331

332+
mc.mutex.Lock()
333+
defer mc.mutex.Unlock()
334+
318335
mc.remoteKeyReceiveCallback = c
319336

320337
return nil
@@ -323,14 +340,14 @@ func RegisterRemoteKeyReceiveCallback(nameSpace string,
323340
// RegisterAuthDataCallback sets up the native callbacks upon
324341
// receiving auth data.
325342
func RegisterAuthDataCallback(nameSpace string, c NativeCallback) error {
326-
mMutex.Lock()
327-
defer mMutex.Unlock()
328-
329-
mc, ok := m[nameSpace]
330-
if !ok {
331-
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)
332346
}
333347

348+
mc.mutex.Lock()
349+
defer mc.mutex.Unlock()
350+
334351
mc.authDataCallback = c
335352

336353
return nil
@@ -340,14 +357,14 @@ func RegisterAuthDataCallback(nameSpace string, c NativeCallback) error {
340357
func InvokeRPC(nameSpace string, rpcName string, requestJSON string,
341358
c NativeCallback) error {
342359

343-
mMutex.Lock()
344-
defer mMutex.Unlock()
345-
346-
mc, ok := m[nameSpace]
347-
if !ok {
348-
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)
349363
}
350364

365+
mc.mutex.Lock()
366+
defer mc.mutex.Unlock()
367+
351368
if rpcName == "" {
352369
return fmt.Errorf("param rpcName required")
353370
}
@@ -385,14 +402,14 @@ func InvokeRPC(nameSpace string, rpcName string, requestJSON string,
385402

386403
// GetExpiry returns the expiration time of the connection macaroon.
387404
func GetExpiry(nameSpace string) (string, error) {
388-
mMutex.Lock()
389-
defer mMutex.Unlock()
390-
391-
mc, ok := m[nameSpace]
392-
if !ok {
393-
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)
394408
}
395409

410+
mc.mutex.Lock()
411+
defer mc.mutex.Unlock()
412+
396413
if mc.mac == nil {
397414
return "", fmt.Errorf("macaroon not obtained yet. GetExpiry" +
398415
"should only be called once the connection is" +
@@ -409,14 +426,14 @@ func GetExpiry(nameSpace string) (string, error) {
409426

410427
// IsReadOnly returns whether or not the connection macaroon is read-only.
411428
func IsReadOnly(nameSpace string) (bool, error) {
412-
mMutex.Lock()
413-
defer mMutex.Unlock()
414-
415-
mc, ok := m[nameSpace]
416-
if !ok {
417-
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)
418432
}
419433

434+
mc.mutex.Lock()
435+
defer mc.mutex.Unlock()
436+
420437
if mc.mac == nil {
421438
log.Errorf("macaroon not obtained yet. IsReadOnly should " +
422439
"only be called once the connection is complete")
@@ -435,16 +452,16 @@ func IsReadOnly(nameSpace string) (bool, error) {
435452
}
436453

437454
// HasPermissions returns whether or not the connection macaroon
438-
// has a specificed permission.
455+
// has a specified permission.
439456
func HasPermissions(nameSpace, permission string) (bool, error) {
440-
mMutex.Lock()
441-
defer mMutex.Unlock()
442-
443-
mc, ok := m[nameSpace]
444-
if !ok {
445-
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)
446460
}
447461

462+
mc.mutex.Lock()
463+
defer mc.mutex.Unlock()
464+
448465
if permission == "" {
449466
return false, nil
450467
}
@@ -558,17 +575,17 @@ func validateArgs(mailboxServer, localPrivKey, remotePubKey string) error {
558575
// parseKeys parses the given keys from their string format and calls callback
559576
// functions where appropriate. NOTE: This function assumes that the parameter
560577
// combinations have been checked by validateArgs.
561-
func parseKeys(nameSpace, localPrivKey, remotePubKey string) (
562-
keychain.SingleKeyECDH, *btcec.PublicKey, error) {
563-
564-
mMutex.Lock()
565-
defer mMutex.Unlock()
578+
func parseKeys(nameSpace, localPrivKey,
579+
remotePubKey string) (keychain.SingleKeyECDH, *btcec.PublicKey, error) {
566580

567-
mc, ok := m[nameSpace]
568-
if !ok {
569-
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)
570584
}
571585

586+
mc.mutex.Lock()
587+
defer mc.mutex.Unlock()
588+
572589
var (
573590
localStaticKey keychain.SingleKeyECDH
574591
remoteStaticKey *btcec.PublicKey

0 commit comments

Comments
 (0)