mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-26 21:41:11 +00:00
chore(@desktop/keycard): improvement in terms of avoiding overlapping keycard library flows
This commit is contained in:
parent
e552a01d2b
commit
608bb38874
@ -170,6 +170,14 @@ proc disconnectAll*(self: Controller) =
|
|||||||
proc delete*(self: Controller) =
|
proc delete*(self: Controller) =
|
||||||
self.disconnectAll()
|
self.disconnectAll()
|
||||||
|
|
||||||
|
proc checkKeycardAvailability*(self: Controller) =
|
||||||
|
if self.keycardService.isBusy():
|
||||||
|
self.keycardService.registerForKeycardAvailability(proc () =
|
||||||
|
self.delegate.keycardReady()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.delegate.keycardReady()
|
||||||
|
|
||||||
proc init*(self: Controller, fullConnect = true) =
|
proc init*(self: Controller, fullConnect = true) =
|
||||||
self.connectKeycardReponseSignal()
|
self.connectKeycardReponseSignal()
|
||||||
|
|
||||||
|
@ -106,6 +106,9 @@ type
|
|||||||
method delete*(self: AccessInterface) {.base.} =
|
method delete*(self: AccessInterface) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method keycardReady*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
|
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
@ -35,6 +35,15 @@ type
|
|||||||
authenticationPopupIsAlreadyRunning: bool
|
authenticationPopupIsAlreadyRunning: bool
|
||||||
runningFlow: FlowType # in general used to mark the global shared flow that is being running (`Authentication` or `Sign`)
|
runningFlow: FlowType # in general used to mark the global shared flow that is being running (`Authentication` or `Sign`)
|
||||||
|
|
||||||
|
# temporary variables used to store data while we're wiating for keycard lib to get ready
|
||||||
|
tmpFlowToRun: FlowType
|
||||||
|
tmpKeyUid: string
|
||||||
|
tmpBip44Paths: seq[string]
|
||||||
|
tmpTxHash: string
|
||||||
|
tmpForceFlow: bool
|
||||||
|
tmpReturnToFlow: FlowType
|
||||||
|
tmpPin: string
|
||||||
|
|
||||||
proc newModule*[T](delegate: T,
|
proc newModule*[T](delegate: T,
|
||||||
uniqueIdentifier: string,
|
uniqueIdentifier: string,
|
||||||
events: EventEmitter,
|
events: EventEmitter,
|
||||||
@ -58,6 +67,10 @@ proc newModule*[T](delegate: T,
|
|||||||
|
|
||||||
{.push warning[Deprecated]: off.}
|
{.push warning[Deprecated]: off.}
|
||||||
|
|
||||||
|
## Forward declarations
|
||||||
|
proc proceedWithSyncKeycardBasedOnAppState[T](self: Module[T], keyUid: string, pin: string)
|
||||||
|
proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, bip44Paths: seq[string], txHash: string, forceFlow: bool, returnToFlow: FlowType)
|
||||||
|
|
||||||
method delete*[T](self: Module[T]) =
|
method delete*[T](self: Module[T]) =
|
||||||
self.view.delete
|
self.view.delete
|
||||||
self.viewVariant.delete
|
self.viewVariant.delete
|
||||||
@ -69,6 +82,12 @@ proc init[T](self: Module[T], fullConnect = true) =
|
|||||||
self.controller.cleanReceivedKeycardData()
|
self.controller.cleanReceivedKeycardData()
|
||||||
self.controller.init(fullConnect)
|
self.controller.init(fullConnect)
|
||||||
|
|
||||||
|
method keycardReady*[T](self: Module[T]) =
|
||||||
|
if self.tmpPin.len > 0:
|
||||||
|
self.proceedWithSyncKeycardBasedOnAppState(self.tmpKeyUid, self.tmpPin)
|
||||||
|
else:
|
||||||
|
self.proceedWithRunFlow(self.tmpFlowToRun, self.tmpKeyUid, self.tmpBip44Paths, self.tmpTxHash, self.tmpForceFlow, self.tmpReturnToFlow)
|
||||||
|
|
||||||
method getModuleAsVariant*[T](self: Module[T]): QVariant =
|
method getModuleAsVariant*[T](self: Module[T]): QVariant =
|
||||||
return self.viewVariant
|
return self.viewVariant
|
||||||
|
|
||||||
@ -318,6 +337,11 @@ method syncKeycardBasedOnAppState*[T](self: Module[T], keyUid: string, pin: stri
|
|||||||
if keyUid.len == 0:
|
if keyUid.len == 0:
|
||||||
debug "cannot sync with the empty keyUid"
|
debug "cannot sync with the empty keyUid"
|
||||||
return
|
return
|
||||||
|
self.tmpKeyUid = keyUid
|
||||||
|
self.tmpPin = pin
|
||||||
|
self.controller.checkKeycardAvailability()
|
||||||
|
|
||||||
|
proc proceedWithSyncKeycardBasedOnAppState[T](self: Module[T], keyUid: string, pin: string) =
|
||||||
self.init(fullConnect = false)
|
self.init(fullConnect = false)
|
||||||
self.controller.setKeyUidWhichIsBeingSyncing(keyUid)
|
self.controller.setKeyUidWhichIsBeingSyncing(keyUid)
|
||||||
self.controller.setPin(pin)
|
self.controller.setPin(pin)
|
||||||
@ -478,6 +502,15 @@ method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Paths
|
|||||||
self.controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
|
self.controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
|
||||||
error "sm_cannot run an general flow"
|
error "sm_cannot run an general flow"
|
||||||
return
|
return
|
||||||
|
self.tmpFlowToRun = flowToRun
|
||||||
|
self.tmpKeyUid = keyUid
|
||||||
|
self.tmpBip44Paths = bip44Paths
|
||||||
|
self.tmpTxHash = txHash
|
||||||
|
self.tmpForceFlow = forceFlow
|
||||||
|
self.tmpReturnToFlow = returnToFlow
|
||||||
|
self.controller.checkKeycardAvailability()
|
||||||
|
|
||||||
|
proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, bip44Paths: seq[string], txHash: string, forceFlow: bool, returnToFlow: FlowType) =
|
||||||
self.init()
|
self.init()
|
||||||
self.view.setForceFlow(forceFlow)
|
self.view.setForceFlow(forceFlow)
|
||||||
self.view.setReturnToFlow(returnToFlow)
|
self.view.setReturnToFlow(returnToFlow)
|
||||||
|
@ -5,8 +5,9 @@
|
|||||||
type
|
type
|
||||||
TimerTaskArg = ref object of QObjectTaskArg
|
TimerTaskArg = ref object of QObjectTaskArg
|
||||||
timeoutInMilliseconds: int
|
timeoutInMilliseconds: int
|
||||||
|
reason: string
|
||||||
|
|
||||||
const timerTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
const timerTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||||
let arg = decode[TimerTaskArg](argEncoded)
|
let arg = decode[TimerTaskArg](argEncoded)
|
||||||
sleep(arg.timeoutInMilliseconds)
|
sleep(arg.timeoutInMilliseconds)
|
||||||
arg.finish("")
|
arg.finish(arg.reason)
|
@ -37,10 +37,15 @@ const SupportedMnemonicLength18* = 18
|
|||||||
const SupportedMnemonicLength24* = 24
|
const SupportedMnemonicLength24* = 24
|
||||||
|
|
||||||
const MnemonicLengthForStatusApp = SupportedMnemonicLength12
|
const MnemonicLengthForStatusApp = SupportedMnemonicLength12
|
||||||
const TimerIntervalInMilliseconds = 3 * 1000 # 3 seconds
|
const ReRunCurrentFlowInterval = 3 * 1000 # 3 seconds
|
||||||
|
const CheckKeycardAvailabilityInterval = 1000 # 1 seconds
|
||||||
|
|
||||||
const SIGNAL_KEYCARD_RESPONSE* = "keycardResponse"
|
const SIGNAL_KEYCARD_RESPONSE* = "keycardResponse"
|
||||||
|
|
||||||
|
type TimerReason {.pure.} = enum
|
||||||
|
ReRunCurrentFlowLater = "ReRunCurrentFlowLater"
|
||||||
|
WaitForKeycardAvailability = "WaitForKeycardAvailability"
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "keycard-service"
|
topics = "keycard-service"
|
||||||
|
|
||||||
@ -63,6 +68,16 @@ QtObject:
|
|||||||
lastReceivedKeycardData: tuple[flowType: string, flowEvent: KeycardEvent]
|
lastReceivedKeycardData: tuple[flowType: string, flowEvent: KeycardEvent]
|
||||||
setPayloadForCurrentFlow: JsonNode
|
setPayloadForCurrentFlow: JsonNode
|
||||||
doLogging: bool
|
doLogging: bool
|
||||||
|
busy: bool
|
||||||
|
waitingFlows: seq[tuple[flow: KCSFlowType, payload: JsonNode]]
|
||||||
|
registeredCallback: proc ()
|
||||||
|
|
||||||
|
## Forward declaration
|
||||||
|
proc startFlow(self: Service, payload: JsonNode)
|
||||||
|
proc runTimer(self: Service, timeoutInMilliseconds: int, reason: string)
|
||||||
|
|
||||||
|
proc isBusy*(self: Service): bool =
|
||||||
|
return self.busy
|
||||||
|
|
||||||
proc delete*(self: Service) =
|
proc delete*(self: Service) =
|
||||||
self.closingApp = true
|
self.closingApp = true
|
||||||
@ -108,7 +123,13 @@ QtObject:
|
|||||||
self.events.emit(SIGNAL_KEYCARD_RESPONSE, KeycardLibArgs(flowType: flowType, flowEvent: flowEvent))
|
self.events.emit(SIGNAL_KEYCARD_RESPONSE, KeycardLibArgs(flowType: flowType, flowEvent: flowEvent))
|
||||||
|
|
||||||
proc receiveKeycardSignal(self: Service, signal: string) {.slot.} =
|
proc receiveKeycardSignal(self: Service, signal: string) {.slot.} =
|
||||||
|
self.busy = false
|
||||||
self.processSignal(signal)
|
self.processSignal(signal)
|
||||||
|
if self.waitingFlows.len > 0:
|
||||||
|
let (flow, payload) = self.waitingFlows[0]
|
||||||
|
self.waitingFlows.delete(0)
|
||||||
|
self.currentFlow = flow
|
||||||
|
self.startFlow(payload)
|
||||||
|
|
||||||
proc getLastReceivedKeycardData*(self: Service): tuple[flowType: string, flowEvent: KeycardEvent] =
|
proc getLastReceivedKeycardData*(self: Service): tuple[flowType: string, flowEvent: KeycardEvent] =
|
||||||
return self.lastReceivedKeycardData
|
return self.lastReceivedKeycardData
|
||||||
@ -132,18 +153,28 @@ QtObject:
|
|||||||
return self.currentFlow
|
return self.currentFlow
|
||||||
|
|
||||||
proc startFlow(self: Service, payload: JsonNode) =
|
proc startFlow(self: Service, payload: JsonNode) =
|
||||||
|
if self.busy:
|
||||||
|
self.waitingFlows.add((flow: self.currentFlow, payload: payload))
|
||||||
|
return
|
||||||
|
self.busy = true
|
||||||
self.updateLocalPayloadForCurrentFlow(payload, cleanBefore = true)
|
self.updateLocalPayloadForCurrentFlow(payload, cleanBefore = true)
|
||||||
let response = keycard_go.keycardStartFlow(self.currentFlow.int, $payload)
|
let response = keycard_go.keycardStartFlow(self.currentFlow.int, $payload)
|
||||||
if self.doLogging:
|
if self.doLogging:
|
||||||
debug "keycardStartFlow", kcServiceCurrFlow=($self.currentFlow), payload=payload, response=response
|
debug "keycardStartFlow", kcServiceCurrFlow=($self.currentFlow), payload=payload, response=response
|
||||||
|
|
||||||
proc resumeFlow(self: Service, payload: JsonNode) =
|
proc resumeFlow(self: Service, payload: JsonNode) =
|
||||||
|
if self.busy:
|
||||||
|
return
|
||||||
|
self.busy = true
|
||||||
self.updateLocalPayloadForCurrentFlow(payload)
|
self.updateLocalPayloadForCurrentFlow(payload)
|
||||||
let response = keycard_go.keycardResumeFlow($payload)
|
let response = keycard_go.keycardResumeFlow($payload)
|
||||||
if self.doLogging:
|
if self.doLogging:
|
||||||
debug "keycardResumeFlow", kcServiceCurrFlow=($self.currentFlow), payload=payload, response=response
|
debug "keycardResumeFlow", kcServiceCurrFlow=($self.currentFlow), payload=payload, response=response
|
||||||
|
|
||||||
proc cancelCurrentFlow*(self: Service) =
|
proc cancelCurrentFlow*(self: Service) =
|
||||||
|
if self.busy:
|
||||||
|
return
|
||||||
|
writeStackTrace()
|
||||||
let response = keycard_go.keycardCancelFlow()
|
let response = keycard_go.keycardCancelFlow()
|
||||||
self.currentFlow = KCSFlowType.NoFlow
|
self.currentFlow = KCSFlowType.NoFlow
|
||||||
if self.doLogging:
|
if self.doLogging:
|
||||||
@ -199,13 +230,23 @@ QtObject:
|
|||||||
result = result & $rand(0 .. 9)
|
result = result & $rand(0 .. 9)
|
||||||
|
|
||||||
proc onTimeout(self: Service, response: string) {.slot.} =
|
proc onTimeout(self: Service, response: string) {.slot.} =
|
||||||
if(self.closingApp or self.currentFlow == KCSFlowType.NoFlow):
|
if response == $TimerReason.ReRunCurrentFlowLater:
|
||||||
return
|
if(self.closingApp or self.currentFlow == KCSFlowType.NoFlow):
|
||||||
if self.doLogging:
|
return
|
||||||
debug "onTimeout, about to start flow: ", kcServiceCurrFlow=($self.currentFlow)
|
if self.doLogging:
|
||||||
self.startFlow(self.setPayloadForCurrentFlow)
|
debug "onTimeout, about to start flow: ", kcServiceCurrFlow=($self.currentFlow)
|
||||||
|
self.startFlow(self.setPayloadForCurrentFlow)
|
||||||
|
elif response == $TimerReason.WaitForKeycardAvailability:
|
||||||
|
if self.busy:
|
||||||
|
self.runTimer(CheckKeycardAvailabilityInterval, $TimerReason.WaitForKeycardAvailability)
|
||||||
|
return
|
||||||
|
if self.registeredCallback != nil:
|
||||||
|
self.registeredCallback()
|
||||||
|
self.registeredCallback = nil
|
||||||
|
else:
|
||||||
|
error "unknown timer reason", reason = response
|
||||||
|
|
||||||
proc runTimer(self: Service) =
|
proc runTimer(self: Service, timeoutInMilliseconds: int, reason: string) =
|
||||||
if(self.closingApp or self.currentFlow == KCSFlowType.NoFlow):
|
if(self.closingApp or self.currentFlow == KCSFlowType.NoFlow):
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -213,7 +254,8 @@ QtObject:
|
|||||||
tptr: cast[ByteAddress](timerTask),
|
tptr: cast[ByteAddress](timerTask),
|
||||||
vptr: cast[ByteAddress](self.vptr),
|
vptr: cast[ByteAddress](self.vptr),
|
||||||
slot: "onTimeout",
|
slot: "onTimeout",
|
||||||
timeoutInMilliseconds: TimerIntervalInMilliseconds
|
timeoutInMilliseconds: timeoutInMilliseconds,
|
||||||
|
reason: reason
|
||||||
)
|
)
|
||||||
self.threadpool.start(arg)
|
self.threadpool.start(arg)
|
||||||
|
|
||||||
@ -440,4 +482,11 @@ QtObject:
|
|||||||
let tmpFlow = self.currentFlow
|
let tmpFlow = self.currentFlow
|
||||||
self.cancelCurrentFlow()
|
self.cancelCurrentFlow()
|
||||||
self.currentFlow = tmpFlow
|
self.currentFlow = tmpFlow
|
||||||
self.runTimer()
|
self.runTimer(ReRunCurrentFlowInterval, "reRunCurrentFlowLater")
|
||||||
|
|
||||||
|
proc registerForKeycardAvailability*(self: Service, p: proc()) =
|
||||||
|
if not self.busy:
|
||||||
|
error "registerForKeycardAvailability can be called only when keycard is busy"
|
||||||
|
return
|
||||||
|
self.registeredCallback = p
|
||||||
|
self.runTimer(CheckKeycardAvailabilityInterval, $TimerReason.WaitForKeycardAvailability)
|
Loading…
x
Reference in New Issue
Block a user