Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2022 Project CHIP Authors 4 : * 5 : * Licensed under the Apache License, Version 2.0 (the "License"); 6 : * you may not use this file except in compliance with the License. 7 : * You may obtain a copy of the License at 8 : * 9 : * http://www.apache.org/licenses/LICENSE-2.0 10 : * 11 : * Unless required by applicable law or agreed to in writing, software 12 : * distributed under the License is distributed on an "AS IS" BASIS, 13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 : * See the License for the specific language governing permissions and 15 : * limitations under the License. 16 : */ 17 : 18 : /** 19 : * @file 20 : * A 'Fail Safe Context' SHALL be created on the receiver, to track fail-safe 21 : * state information while the fail-safe is armed. 22 : */ 23 : 24 : #pragma once 25 : 26 : #include <lib/core/CHIPError.h> 27 : #include <lib/core/DataModelTypes.h> 28 : #include <platform/internal/CHIPDeviceLayerInternal.h> 29 : #include <system/SystemClock.h> 30 : 31 : namespace chip { 32 : namespace app { 33 : 34 : class FailSafeContext 35 : { 36 : public: 37 : // ===== Members for internal use by other Device Layer components. 38 : 39 : /** 40 : * @brief 41 : * Only a single fail-safe timer is started on the device, if this function is called again 42 : * when the fail-safe timer is currently armed, the currently-running fail-safe timer will 43 : * first be cancelled, then the fail-safe timer will be re-armed. 44 : */ 45 : CHIP_ERROR ArmFailSafe(FabricIndex accessingFabricIndex, System::Clock::Seconds16 expiryLengthSeconds); 46 : 47 : /** 48 : * @brief Cleanly disarm failsafe timer, such as on CommissioningComplete 49 : */ 50 : void DisarmFailSafe(); 51 : void SetAddNocCommandInvoked(FabricIndex nocFabricIndex) 52 : { 53 : mAddNocCommandHasBeenInvoked = true; 54 : mFabricIndex = nocFabricIndex; 55 : } 56 : void SetUpdateNocCommandInvoked() { mUpdateNocCommandHasBeenInvoked = true; } 57 : void SetAddTrustedRootCertInvoked() { mAddTrustedRootCertHasBeenInvoked = true; } 58 : void SetCsrRequestForUpdateNoc(bool isForUpdateNoc) { mIsCsrRequestForUpdateNoc = isForUpdateNoc; } 59 : 60 : /** 61 : * @brief 62 : * Schedules a work to cleanup the FailSafe Context asynchronously after various cleanup work 63 : * has completed. 64 : */ 65 : void ScheduleFailSafeCleanup(FabricIndex fabricIndex, bool addNocCommandInvoked, bool updateNocCommandInvoked); 66 : 67 : bool IsFailSafeArmed(FabricIndex accessingFabricIndex) const 68 : { 69 : return IsFailSafeArmed() && MatchesFabricIndex(accessingFabricIndex); 70 : } 71 : 72 : // Returns true if the fail-safe is in a state where commands that require an armed 73 : // fail-safe can no longer execute, but a new fail-safe can't be armed yet. 74 8 : bool IsFailSafeBusy() const { return mFailSafeBusy; } 75 : 76 6 : bool IsFailSafeArmed() const { return mFailSafeArmed; } 77 : 78 : // True if it is possible to do an initial arming of the failsafe if needed. 79 : // To be used in places where some action should take place only if the 80 : // fail-safe could be armed after that action. 81 6 : bool IsFailSafeFullyDisarmed() const { return !IsFailSafeArmed() && !IsFailSafeBusy(); } 82 : 83 : bool MatchesFabricIndex(FabricIndex accessingFabricIndex) const 84 : { 85 : VerifyOrDie(IsFailSafeArmed()); 86 : return (accessingFabricIndex == mFabricIndex); 87 : } 88 : 89 : bool NocCommandHasBeenInvoked() const { return mAddNocCommandHasBeenInvoked || mUpdateNocCommandHasBeenInvoked; } 90 : bool AddNocCommandHasBeenInvoked() const { return mAddNocCommandHasBeenInvoked; } 91 : bool UpdateNocCommandHasBeenInvoked() const { return mUpdateNocCommandHasBeenInvoked; } 92 : bool AddTrustedRootCertHasBeenInvoked() const { return mAddTrustedRootCertHasBeenInvoked; } 93 : bool IsCsrRequestForUpdateNoc() const { return mIsCsrRequestForUpdateNoc; } 94 : 95 : FabricIndex GetFabricIndex() const 96 : { 97 : VerifyOrDie(IsFailSafeArmed()); 98 : return mFabricIndex; 99 : } 100 : 101 : // Immediately disarms the timer and schedules a failsafe timer expiry. 102 : // If the failsafe is not armed, this is a no-op. 103 : void ForceFailSafeTimerExpiry(); 104 : 105 : private: 106 : bool mFailSafeArmed = false; 107 : bool mFailSafeBusy = false; 108 : bool mAddNocCommandHasBeenInvoked = false; 109 : bool mUpdateNocCommandHasBeenInvoked = false; 110 : bool mAddTrustedRootCertHasBeenInvoked = false; 111 : // The fact of whether a CSR occurred at all is stored elsewhere. 112 : bool mIsCsrRequestForUpdateNoc = false; 113 : FabricIndex mFabricIndex = kUndefinedFabricIndex; 114 : 115 : /** 116 : * @brief 117 : * The callback function to be called when "fail-safe timer" expires. 118 : */ 119 : static void HandleArmFailSafeTimer(System::Layer * layer, void * aAppState); 120 : 121 : /** 122 : * @brief 123 : * The callback function to be called when max cumulative time expires. 124 : */ 125 : static void HandleMaxCumulativeFailSafeTimer(System::Layer * layer, void * aAppState); 126 : 127 : /** 128 : * @brief 129 : * The callback function to be called asynchronously after various cleanup work has completed 130 : * to actually disarm the fail-safe. 131 : */ 132 : static void HandleDisarmFailSafe(intptr_t arg); 133 : 134 : void SetFailSafeArmed(bool armed); 135 : 136 : /** 137 : * @brief Reset to unarmed basic state 138 : */ 139 2 : void ResetState() 140 : { 141 2 : SetFailSafeArmed(false); 142 : 143 2 : mAddNocCommandHasBeenInvoked = false; 144 2 : mUpdateNocCommandHasBeenInvoked = false; 145 2 : mAddTrustedRootCertHasBeenInvoked = false; 146 2 : mFailSafeBusy = false; 147 2 : mIsCsrRequestForUpdateNoc = false; 148 2 : } 149 : 150 : void FailSafeTimerExpired(); 151 : CHIP_ERROR CommitToStorage(); 152 : }; 153 : 154 : } // namespace app 155 : } // namespace chip