@@ -50,6 +50,8 @@ type mobileClient struct {
5050 localPrivCreateCallback NativeCallback
5151 remoteKeyReceiveCallback NativeCallback
5252 authDataCallback NativeCallback
53+
54+ mutex sync.Mutex
5355}
5456
5557func newMobileClient () * mobileClient {
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.
105121func 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.
238255func 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.
251268func 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.
271288func 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) {
289306func 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,
307324func 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.
325342func 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 {
340357func 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.
387404func 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.
411428func 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.
439456func 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