]> git.saurik.com Git - apple/security.git/blob - keychain/ot/OctagonStateMachine.h
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / ot / OctagonStateMachine.h
1
2 #if OCTAGON
3
4 #import <Foundation/Foundation.h>
5 #import "keychain/ckks/CKKSResultOperation.h"
6 #import "keychain/ckks/CKKSCondition.h"
7 #import "keychain/ckks/CKKSLockStateTracker.h"
8
9 #import "keychain/ot/OctagonStateMachineHelpers.h"
10 #import "keychain/ot/OctagonStateMachineObservers.h"
11 #import "keychain/ot/OctagonFlags.h"
12 #import "keychain/ot/OctagonPendingFlag.h"
13
14 NS_ASSUME_NONNULL_BEGIN
15
16 @protocol OctagonStateOnqueuePendingFlagHandler
17 - (void)_onqueueHandlePendingFlag:(OctagonPendingFlag*)pendingFlag;
18 @end
19
20 // A State Machine Engine provides the actual implementation of a state machine.
21 // Its sole callback will be called on the queue passed into the OctagonStateMachine.
22 // Its inputs are the current state, and any interrupt flags that have been set on the state machine.
23
24 // The returned operation should not yet be started; the state machine will run it.
25 // Return nil if there's nothing to be done yet; the state machine will remain in the currentState until poked.
26 // The engine will be held weakly, so, ensure you keep it around.
27 @protocol OctagonStateMachineEngine
28 - (CKKSResultOperation<OctagonStateTransitionOperationProtocol>* _Nullable)_onqueueNextStateMachineTransition:(OctagonState*)currentState
29 flags:(OctagonFlags*)flags
30 pendingFlags:(id<OctagonStateOnqueuePendingFlagHandler>)pendingFlagHandler;
31 @end
32
33 @protocol OctagonStateFlagHandler
34 - (void)handleFlag:(OctagonFlag*)flag;
35 - (void)handlePendingFlag:(OctagonPendingFlag*)pendingFlag;
36
37 // If you've truly broken your queue ordering, then call this from whatever queue your flag handler is using.
38 - (void)_onqueueHandleFlag:(OctagonFlag*)flag;
39 @end
40
41 @interface OctagonStateMachine : NSObject <OctagonStateFlagHandler, OctagonStateOnqueuePendingFlagHandler>
42 @property (readonly) OctagonState* currentState;
43
44 // The state machine transition function is the only location which should remove flags.
45 // Adding flags should use -handleFlag on the state machine
46 @property (readonly) id<OctagonFlagContainer> flags;
47
48 @property NSMutableDictionary<OctagonState*, CKKSCondition*>* stateConditions;
49
50 @property (readonly) CKKSCondition* paused;
51
52 @property (readonly) NSSet* allowableStates;
53 @property (nonatomic) uint64_t timeout;
54
55 @property (nullable) CKKSLockStateTracker* lockStateTracker;
56
57 // If you don't pass a lock state tracker, then you cannot reasonably use OctagonPendingConditionsDeviceUnlocked
58
59 - (instancetype)initWithName:(NSString*)name
60 states:(NSSet<OctagonState*>*)possibleStates
61 flags:(NSSet<OctagonFlag*>*)possibleFlags
62 initialState:(OctagonState*)initialState
63 queue:(dispatch_queue_t)queue
64 stateEngine:(id<OctagonStateMachineEngine>)stateEngine
65 lockStateTracker:(CKKSLockStateTracker*)lockStateTracker;
66
67 - (void)startOperation;
68 - (void)haltOperation;
69
70 // If the state machine is paused, this will kick it to start up again. Otherwise, it is a no-op.
71 - (void)pokeStateMachine;
72 - (void)_onqueuePokeStateMachine;
73
74 // This will set the given flag, and ensure that the state machine spins to handle it.
75 - (void)handleFlag:(OctagonFlag*)flag;
76 - (void)_onqueueHandleFlag:(OctagonFlag*)flag;
77
78 // This will schedule the flag for future addition
79 - (void)handlePendingFlag:(OctagonPendingFlag *)pendingFlag;
80
81 - (NSDictionary<NSString*, NSString*>*)dumpPendingFlags;
82 // For testing
83 - (NSArray<OctagonFlag*>*)possiblePendingFlags;
84 - (void)disablePendingFlags;
85
86 - (void)handleExternalRequest:(OctagonStateTransitionRequest<CKKSResultOperation<OctagonStateTransitionOperationProtocol>*>*)request;
87
88 - (void)registerStateTransitionWatcher:(OctagonStateTransitionWatcher*)watcher;
89 - (void)registerMultiStateArrivalWatcher:(OctagonStateMultiStateArrivalWatcher*)watcher;
90
91 - (void)doSimpleStateMachineRPC:(NSString*)name
92 op:(CKKSResultOperation<OctagonStateTransitionOperationProtocol>*)op
93 sourceStates:(NSSet<OctagonState*>*)sourceStates
94 reply:(nonnull void (^)(NSError * _Nullable))reply;
95
96 - (CKKSResultOperation*)doWatchedStateMachineRPC:(NSString*)name
97 sourceStates:(NSSet<OctagonState*>*)sourceStates
98 path:(OctagonStateTransitionPath*)path
99 reply:(nonnull void (^)(NSError *error))reply;
100 - (void)setWatcherTimeout:(uint64_t)timeout;
101 - (BOOL)isPaused;
102
103 // Wait the state `wantedState' for `timeout' ns, if we transition though that state
104 // return that state, otherwise return a snapshot. No garantee that you still are in that state,
105 // if you want that, you need to run an RPC.
106 - (OctagonState* _Nonnull)waitForState:(OctagonState* _Nonnull)wantedState wait:(uint64_t)timeout;
107
108 @end
109
110 NS_ASSUME_NONNULL_END
111
112 #endif