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