github.com/status-im/status-go@v1.1.0/server/pairing/statecontrol/state_management.go (about)

     1  package statecontrol
     2  
     3  // TODO refactor into the pairing package once the backend dependencies have been removed.
     4  
     5  import (
     6  	"fmt"
     7  	"sync"
     8  )
     9  
    10  var (
    11  	ErrProcessStateManagerAlreadyPairing = fmt.Errorf("cannot start new LocalPairing session, already pairing")
    12  	ErrProcessStateManagerAlreadyPaired  = func(sessionName string) error {
    13  		return fmt.Errorf("given connection string already successfully used '%s'", sessionName)
    14  	}
    15  )
    16  
    17  // ProcessStateManager represents a g
    18  type ProcessStateManager struct {
    19  	pairing     bool
    20  	pairingLock sync.Mutex
    21  
    22  	// sessions represents a map[string]bool:
    23  	// where string is a ConnectionParams string and bool is the transfer success state of that connection string
    24  	sessions sync.Map
    25  }
    26  
    27  // IsPairing returns if the ProcessStateManager is currently in pairing mode
    28  func (psm *ProcessStateManager) IsPairing() bool {
    29  	psm.pairingLock.Lock()
    30  	defer psm.pairingLock.Unlock()
    31  	return psm.pairing
    32  }
    33  
    34  // SetPairing sets the ProcessStateManager pairing state
    35  func (psm *ProcessStateManager) SetPairing(state bool) {
    36  	psm.pairingLock.Lock()
    37  	defer psm.pairingLock.Unlock()
    38  	psm.pairing = state
    39  }
    40  
    41  // RegisterSession stores a sessionName with the default false value.
    42  // In practice a sessionName will be a ConnectionParams string provided by the server mode device.
    43  // The boolean value represents whether the ConnectionParams string session resulted in a successful transfer.
    44  func (psm *ProcessStateManager) RegisterSession(sessionName string) {
    45  	psm.sessions.Store(sessionName, false)
    46  }
    47  
    48  // CompleteSession updates a transfer session with a given transfer success state only if the session is registered.
    49  func (psm *ProcessStateManager) CompleteSession(sessionName string) {
    50  	r, c := psm.GetSession(sessionName)
    51  	if r && !c {
    52  		psm.sessions.Store(sessionName, true)
    53  	}
    54  }
    55  
    56  // GetSession returns two booleans for a given sessionName.
    57  // These represent if the sessionName has been registered and if it has resulted in a successful transfer
    58  func (psm *ProcessStateManager) GetSession(sessionName string) (bool, bool) {
    59  	completed, registered := psm.sessions.Load(sessionName)
    60  	if !registered {
    61  		return registered, false
    62  	}
    63  	return registered, completed.(bool)
    64  }
    65  
    66  // StartPairing along with StopPairing are the core functions of the ProcessStateManager
    67  // This function takes a sessionName, which in practice is a ConnectionParams string, and attempts to init pairing state management.
    68  // The function will return an error if the ProcessStateManager is already currently pairing or if the sessionName was previously successful.
    69  func (psm *ProcessStateManager) StartPairing(sessionName string) error {
    70  	if psm.IsPairing() {
    71  		return ErrProcessStateManagerAlreadyPairing
    72  	}
    73  
    74  	registered, completed := psm.GetSession(sessionName)
    75  	if completed {
    76  		return ErrProcessStateManagerAlreadyPaired(sessionName)
    77  	}
    78  	if !registered {
    79  		psm.RegisterSession(sessionName)
    80  	}
    81  
    82  	psm.SetPairing(true)
    83  	return nil
    84  }
    85  
    86  // StopPairing takes a sessionName and an error, if the error is nil the sessionName will be recorded as successful
    87  // the pairing state of the ProcessStateManager is set to false.
    88  func (psm *ProcessStateManager) StopPairing(sessionName string, err error) {
    89  	if err == nil {
    90  		psm.CompleteSession(sessionName)
    91  	}
    92  	psm.SetPairing(false)
    93  }