blob: 271f72ec107f3bddd9733516becbbdd610da14ea [file] [log] [blame]
yunhanw-googleef040a72021-05-05 07:17:56 -07001/**
2 *
3 * Copyright (c) 2021 Project CHIP Authors
4 * Copyright (c) 2015-2017 Nest Labs, Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
Song GUO1ccc2af2022-03-03 01:53:33 +080019#include <access/AccessControl.h>
20#include <access/RequestPath.h>
21#include <access/SubjectDescriptor.h>
yunhanw-googleef040a72021-05-05 07:17:56 -070022#include <app/EventManagement.h>
23#include <app/InteractionModelEngine.h>
Song GUO1ccc2af2022-03-03 01:53:33 +080024#include <app/RequiredPrivilege.h>
yunhanw-google07fc8cd2022-03-24 01:41:28 -070025#include <assert.h>
yunhanw-googleef040a72021-05-05 07:17:56 -070026#include <inttypes.h>
Martin Turon82bfcd52023-01-09 13:30:38 -080027#include <lib/core/TLVUtilities.h>
Zang MingJie53dd5832021-09-03 03:05:16 +080028#include <lib/support/CodeUtils.h>
Zang MingJie53dd5832021-09-03 03:05:16 +080029#include <lib/support/logging/CHIPLogging.h>
yunhanw-googleef040a72021-05-05 07:17:56 -070030
31using namespace chip::TLV;
32
33namespace chip {
34namespace app {
Justin Wood3c96d5b2024-07-10 11:20:24 -100035static EventManagement sInstance;
yunhanw-googleef040a72021-05-05 07:17:56 -070036
37/**
38 * @brief
39 * A TLVReader backed by CircularEventBuffer
40 */
41class CircularEventReader : public TLV::TLVReader
42{
43public:
44 /**
45 * @brief
46 * Initializes a TLVReader object backed by CircularEventBuffer
47 *
48 * Reading begins in the CircularTLVBuffer belonging to this
49 * CircularEventBuffer. When the reader runs out of data, it begins
50 * to read from the previous CircularEventBuffer.
51 *
52 * @param[in] apBuf A pointer to a fully initialized CircularEventBuffer
53 *
54 */
55 void Init(CircularEventBufferWrapper * apBuf);
56
57 virtual ~CircularEventReader() = default;
58};
59
Arkadiusz Bokowy52e228f2022-11-29 12:42:40 +010060EventManagement & EventManagement::GetInstance()
yunhanw-googleef040a72021-05-05 07:17:56 -070061{
62 return sInstance;
63}
64
65struct ReclaimEventCtx
66{
67 CircularEventBuffer * mpEventBuffer = nullptr;
68 size_t mSpaceNeededForMovedEvent = 0;
69};
70
71/**
72 * @brief
73 * Internal structure for traversing event list.
74 */
75struct CopyAndAdjustDeltaTimeContext
76{
77 CopyAndAdjustDeltaTimeContext(TLVWriter * aWriter, EventLoadOutContext * inContext) : mpWriter(aWriter), mpContext(inContext) {}
78
79 TLV::TLVWriter * mpWriter = nullptr;
80 EventLoadOutContext * mpContext = nullptr;
81};
82
yunhanw-google2423a262021-06-07 14:06:34 -070083void EventManagement::Init(Messaging::ExchangeManager * apExchangeManager, uint32_t aNumBuffers,
yunhanw-google9a74bae2021-12-15 13:33:05 -080084 CircularEventBuffer * apCircularEventBuffer, const LogStorageResources * const apLogStorageResources,
Boris Zbarsky7c77e8e2023-02-23 11:23:27 -050085 MonotonicallyIncreasingCounter<EventNumber> * apEventNumberCounter,
86 System::Clock::Milliseconds64 aMonotonicStartupTime)
yunhanw-googleef040a72021-05-05 07:17:56 -070087{
88 CircularEventBuffer * current = nullptr;
89 CircularEventBuffer * prev = nullptr;
90 CircularEventBuffer * next = nullptr;
91
yunhanw-google2423a262021-06-07 14:06:34 -070092 if (aNumBuffers == 0)
93 {
94 ChipLogError(EventLogging, "Invalid aNumBuffers");
95 return;
96 }
yunhanw-googleef040a72021-05-05 07:17:56 -070097
yunhanw-google2423a262021-06-07 14:06:34 -070098 if (mState != EventManagementStates::Shutdown)
99 {
100 ChipLogError(EventLogging, "Invalid EventManagement State");
101 return;
102 }
yunhanw-googleef040a72021-05-05 07:17:56 -0700103 mpExchangeMgr = apExchangeManager;
104
yunhanw-google2423a262021-06-07 14:06:34 -0700105 for (uint32_t bufferIndex = 0; bufferIndex < aNumBuffers; bufferIndex++)
yunhanw-googleef040a72021-05-05 07:17:56 -0700106 {
107 next = (bufferIndex < aNumBuffers - 1) ? &apCircularEventBuffer[bufferIndex + 1] : nullptr;
108
109 current = &apCircularEventBuffer[bufferIndex];
110 current->Init(apLogStorageResources[bufferIndex].mpBuffer, apLogStorageResources[bufferIndex].mBufferSize, prev, next,
111 apLogStorageResources[bufferIndex].mPriority);
112
113 prev = current;
114
yunhanw-googlea6e4d4b2022-03-02 10:33:30 -0800115 current->mProcessEvictedElement = nullptr;
yunhanw-googleef040a72021-05-05 07:17:56 -0700116 current->mAppData = nullptr;
yunhanw-googleef040a72021-05-05 07:17:56 -0700117 }
118
Boris Zbarskycc3a98c2022-04-14 23:15:16 -0400119 mpEventNumberCounter = apEventNumberCounter;
120 mLastEventNumber = mpEventNumberCounter->GetValue();
yunhanw-google9a74bae2021-12-15 13:33:05 -0800121
yunhanw-googleef040a72021-05-05 07:17:56 -0700122 mpEventBuffer = apCircularEventBuffer;
123 mState = EventManagementStates::Idle;
124 mBytesWritten = 0;
Boris Zbarsky7c77e8e2023-02-23 11:23:27 -0500125
126 mMonotonicStartupTime = aMonotonicStartupTime;
yunhanw-googleef040a72021-05-05 07:17:56 -0700127}
128
129CHIP_ERROR EventManagement::CopyToNextBuffer(CircularEventBuffer * apEventBuffer)
130{
131 CircularTLVWriter writer;
132 CircularTLVReader reader;
133 CHIP_ERROR err = CHIP_NO_ERROR;
134 CircularEventBuffer * nextBuffer = apEventBuffer->GetNextCircularEventBuffer();
135 if (nextBuffer == nullptr)
136 {
137 return CHIP_ERROR_INVALID_ARGUMENT;
138 }
139 CircularEventBuffer backup = *nextBuffer;
140
141 // Set up the next buffer s.t. it fails if needs to evict an element
142 nextBuffer->mProcessEvictedElement = AlwaysFail;
143
144 writer.Init(*nextBuffer);
145
146 // Set up the reader s.t. it is positioned to read the head event
147 reader.Init(*apEventBuffer);
148
149 err = reader.Next();
150 SuccessOrExit(err);
151
152 err = writer.CopyElement(reader);
153 SuccessOrExit(err);
154
155 err = writer.Finalize();
156 SuccessOrExit(err);
157
Kamil Kasperczykae5a36a2022-03-23 09:54:22 +0100158 ChipLogDetail(EventLogging, "Copy Event to next buffer with priority %u", static_cast<unsigned>(nextBuffer->GetPriority()));
yunhanw-googleef040a72021-05-05 07:17:56 -0700159exit:
160 if (err != CHIP_NO_ERROR)
161 {
162 *nextBuffer = backup;
163 }
164 return err;
165}
166
Boris Zbarskyb236bfb2023-02-23 11:51:11 -0500167CHIP_ERROR EventManagement::EnsureSpaceInCircularBuffer(size_t aRequiredSpace, PriorityLevel aPriority)
yunhanw-googleef040a72021-05-05 07:17:56 -0700168{
169 CHIP_ERROR err = CHIP_NO_ERROR;
170 size_t requiredSpace = aRequiredSpace;
171 CircularEventBuffer * eventBuffer = mpEventBuffer;
172 ReclaimEventCtx ctx;
173
Boris Zbarskyb236bfb2023-02-23 11:51:11 -0500174 // Check that we have this much space in all our event buffers that might
175 // hold the event. If we do not, that will prevent the event from being
Arkadiusz Bokowy42b424d2023-06-07 17:50:19 +0200176 // properly evicted into higher-priority buffers. We want to discover
Boris Zbarskyb236bfb2023-02-23 11:51:11 -0500177 // this early, so that testing surfaces the need to make those buffers
178 // larger.
179 for (auto * currentBuffer = mpEventBuffer; currentBuffer; currentBuffer = currentBuffer->GetNextCircularEventBuffer())
180 {
181 VerifyOrExit(requiredSpace <= currentBuffer->GetTotalDataLength(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
182 if (currentBuffer->IsFinalDestinationForPriority(aPriority))
183 {
184 break;
185 }
186 }
187
dependabot[bot]c53bef22023-05-26 14:17:52 +0000188 VerifyOrExit(eventBuffer != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
189
yunhanw-googleef040a72021-05-05 07:17:56 -0700190 // check whether we actually need to do anything, exit if we don't
191 VerifyOrExit(requiredSpace > eventBuffer->AvailableDataLength(), err = CHIP_NO_ERROR);
192
193 while (true)
194 {
yunhanw-googleef040a72021-05-05 07:17:56 -0700195 if (requiredSpace > eventBuffer->AvailableDataLength())
196 {
197 ctx.mpEventBuffer = eventBuffer;
198 ctx.mSpaceNeededForMovedEvent = 0;
199
200 eventBuffer->mProcessEvictedElement = EvictEvent;
201 eventBuffer->mAppData = &ctx;
202 err = eventBuffer->EvictHead();
203
204 // one of two things happened: either the element was evicted immediately if the head's priority is same as current
205 // buffer(final one), or we figured out how much space we need to evict it into the next buffer, the check happens in
206 // EvictEvent function
207
208 if (err != CHIP_NO_ERROR)
209 {
210 VerifyOrExit(ctx.mSpaceNeededForMovedEvent != 0, /* no-op, return err */);
211 VerifyOrExit(eventBuffer->GetNextCircularEventBuffer() != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
212 if (ctx.mSpaceNeededForMovedEvent <= eventBuffer->GetNextCircularEventBuffer()->AvailableDataLength())
213 {
214 // we can copy the event outright. copy event and
215 // subsequently evict head s.t. evicting the head
216 // element always succeeds.
217 // Since we're calling CopyElement and we've checked
218 // that there is space in the next buffer, we don't expect
219 // this to fail.
220 err = CopyToNextBuffer(eventBuffer);
221 SuccessOrExit(err);
222 // success; evict head unconditionally
223 eventBuffer->mProcessEvictedElement = nullptr;
224 err = eventBuffer->EvictHead();
225 // if unconditional eviction failed, this
226 // means that we have no way of further
227 // clearing the buffer. fail out and let the
228 // caller know that we could not honor the
229 // request
230 SuccessOrExit(err);
231 continue;
232 }
233 // we cannot copy event outright. We remember the
234 // current required space in mRequiredSpaceForEvicted, we note the
235 // space requirements for the event in the current
236 // buffer and make that space in the next buffer.
237 eventBuffer->SetRequiredSpaceforEvicted(requiredSpace);
238 eventBuffer = eventBuffer->GetNextCircularEventBuffer();
239
240 // Sanity check: return error here on null event buffer. If
241 // eventBuffer->mpNext were null, then the `EvictBuffer`
242 // would have succeeded -- the event was
243 // already in the final buffer.
244 VerifyOrExit(eventBuffer != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
245 requiredSpace = ctx.mSpaceNeededForMovedEvent;
246 }
247 }
248 else
249 {
250 // this branch is only taken when we go back in the buffer chain since we have free/spare enough space in next buffer,
251 // and need to retry to copy event from current buffer to next buffer, and free space for current buffer
252 if (eventBuffer == mpEventBuffer)
253 break;
254 eventBuffer = eventBuffer->GetPreviousCircularEventBuffer();
255 requiredSpace = eventBuffer->GetRequiredSpaceforEvicted();
256 err = CHIP_NO_ERROR;
257 }
258 }
259
yunhanw-googlea6e4d4b2022-03-02 10:33:30 -0800260 mpEventBuffer->mProcessEvictedElement = nullptr;
yunhanw-googleef040a72021-05-05 07:17:56 -0700261 mpEventBuffer->mAppData = nullptr;
262
263exit:
yunhanw-googleef040a72021-05-05 07:17:56 -0700264 return err;
265}
266
267CHIP_ERROR EventManagement::CalculateEventSize(EventLoggingDelegate * apDelegate, const EventOptions * apOptions,
268 uint32_t & requiredSize)
269{
yunhanw-googleef040a72021-05-05 07:17:56 -0700270 System::PacketBufferTLVWriter writer;
yunhanw-google9a74bae2021-12-15 13:33:05 -0800271 EventLoadOutContext ctxt = EventLoadOutContext(writer, apOptions->mPriority, GetLastEventNumber());
yunhanw-googleef040a72021-05-05 07:17:56 -0700272 System::PacketBufferHandle buf = System::PacketBufferHandle::New(kMaxEventSizeReserve);
273 if (buf.IsNull())
274 {
275 return CHIP_ERROR_NO_MEMORY;
276 }
277 writer.Init(std::move(buf));
278
yunhanw-google9a74bae2021-12-15 13:33:05 -0800279 ctxt.mCurrentEventNumber = mLastEventNumber;
280 ctxt.mCurrentTime = mLastEventTimestamp;
281 CHIP_ERROR err = ConstructEvent(&ctxt, apDelegate, apOptions);
282 if (err == CHIP_NO_ERROR)
yunhanw-googleef040a72021-05-05 07:17:56 -0700283 {
yunhanw-google9a74bae2021-12-15 13:33:05 -0800284 requiredSize = writer.GetLengthWritten();
yunhanw-googleef040a72021-05-05 07:17:56 -0700285 }
286 return err;
287}
288
289CHIP_ERROR EventManagement::ConstructEvent(EventLoadOutContext * apContext, EventLoggingDelegate * apDelegate,
290 const EventOptions * apOptions)
291{
yunhanw-google299393b2021-12-06 09:59:34 -0800292 VerifyOrReturnError(apContext->mCurrentEventNumber >= apContext->mStartingEventNumber, CHIP_NO_ERROR
293 /* no-op: don't write event, but advance current event Number */);
yunhanw-googleef040a72021-05-05 07:17:56 -0700294
yunhanw-google299393b2021-12-06 09:59:34 -0800295 VerifyOrReturnError(apOptions != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
yunhanw-googleef040a72021-05-05 07:17:56 -0700296
yunhanw-google299393b2021-12-06 09:59:34 -0800297 EventReportIB::Builder eventReportBuilder;
yunhanw-googlea6e4d4b2022-03-02 10:33:30 -0800298 ReturnErrorOnFailure(eventReportBuilder.Init(&(apContext->mWriter)));
yunhanw-google299393b2021-12-06 09:59:34 -0800299 EventDataIB::Builder & eventDataIBBuilder = eventReportBuilder.CreateEventData();
300 ReturnErrorOnFailure(eventReportBuilder.GetError());
301 EventPathIB::Builder & eventPathBuilder = eventDataIBBuilder.CreatePath();
302 ReturnErrorOnFailure(eventDataIBBuilder.GetError());
yunhanw-googleef040a72021-05-05 07:17:56 -0700303
Boris Zbarskydf1f7a82023-05-29 11:24:25 -0400304 CHIP_ERROR err = eventPathBuilder.Endpoint(apOptions->mPath.mEndpointId)
305 .Cluster(apOptions->mPath.mClusterId)
306 .Event(apOptions->mPath.mEventId)
307 .EndOfEventPathIB();
308 ReturnErrorOnFailure(err);
yunhanw-google9a74bae2021-12-15 13:33:05 -0800309 eventDataIBBuilder.EventNumber(apContext->mCurrentEventNumber).Priority(chip::to_underlying(apContext->mPriority));
yunhanw-google299393b2021-12-06 09:59:34 -0800310 ReturnErrorOnFailure(eventDataIBBuilder.GetError());
yunhanw-googleef040a72021-05-05 07:17:56 -0700311
yunhanw-google7b7374a2021-12-01 11:08:09 -0800312 if (apOptions->mTimestamp.IsSystem())
313 {
yunhanw-google9a74bae2021-12-15 13:33:05 -0800314 eventDataIBBuilder.SystemTimestamp(apOptions->mTimestamp.mValue);
yunhanw-google7b7374a2021-12-01 11:08:09 -0800315 }
316 else
317 {
yunhanw-google9a74bae2021-12-15 13:33:05 -0800318 eventDataIBBuilder.EpochTimestamp(apOptions->mTimestamp.mValue);
yunhanw-google7b7374a2021-12-01 11:08:09 -0800319 }
320
yunhanw-google299393b2021-12-06 09:59:34 -0800321 ReturnErrorOnFailure(eventDataIBBuilder.GetError());
yunhanw-googleef040a72021-05-05 07:17:56 -0700322
yunhanw-googleef040a72021-05-05 07:17:56 -0700323 // Callback to write the EventData
yunhanw-google299393b2021-12-06 09:59:34 -0800324 ReturnErrorOnFailure(apDelegate->WriteEvent(apContext->mWriter));
yunhanw-googlee4508322022-01-26 18:27:51 -0800325
326 // The fabricIndex profile tag is internal use only for fabric filtering when retrieving event from circular event buffer,
327 // and would not go on the wire.
yunhanw-googlec438b892022-05-05 09:31:07 -0700328 // Revisit FabricRemovedCB function should the encoding of fabricIndex change in the future.
yunhanw-googlee4508322022-01-26 18:27:51 -0800329 if (apOptions->mFabricIndex != kUndefinedFabricIndex)
330 {
331 apContext->mWriter.Put(TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag), apOptions->mFabricIndex);
332 }
Boris Zbarskydf1f7a82023-05-29 11:24:25 -0400333 ReturnErrorOnFailure(eventDataIBBuilder.EndOfEventDataIB());
334 ReturnErrorOnFailure(eventReportBuilder.EndOfEventReportIB());
yunhanw-google299393b2021-12-06 09:59:34 -0800335 ReturnErrorOnFailure(apContext->mWriter.Finalize());
yunhanw-googleef040a72021-05-05 07:17:56 -0700336 apContext->mFirst = false;
yunhanw-google299393b2021-12-06 09:59:34 -0800337 return CHIP_NO_ERROR;
yunhanw-googleef040a72021-05-05 07:17:56 -0700338}
339
yunhanw-google2423a262021-06-07 14:06:34 -0700340void EventManagement::CreateEventManagement(Messaging::ExchangeManager * apExchangeManager, uint32_t aNumBuffers,
yunhanw-googleef040a72021-05-05 07:17:56 -0700341 CircularEventBuffer * apCircularEventBuffer,
yunhanw-google9a74bae2021-12-15 13:33:05 -0800342 const LogStorageResources * const apLogStorageResources,
Boris Zbarsky7c77e8e2023-02-23 11:23:27 -0500343 MonotonicallyIncreasingCounter<EventNumber> * apEventNumberCounter,
344 System::Clock::Milliseconds64 aMonotonicStartupTime)
yunhanw-googleef040a72021-05-05 07:17:56 -0700345{
346
Boris Zbarsky7c77e8e2023-02-23 11:23:27 -0500347 sInstance.Init(apExchangeManager, aNumBuffers, apCircularEventBuffer, apLogStorageResources, apEventNumberCounter,
348 aMonotonicStartupTime);
yunhanw-googleef040a72021-05-05 07:17:56 -0700349}
350
351/**
352 * @brief Perform any actions we need to on shutdown.
353 */
354void EventManagement::DestroyEventManagement()
355{
yunhanw-googleef040a72021-05-05 07:17:56 -0700356 sInstance.mState = EventManagementStates::Shutdown;
357 sInstance.mpEventBuffer = nullptr;
358 sInstance.mpExchangeMgr = nullptr;
yunhanw-googleef040a72021-05-05 07:17:56 -0700359}
360
yunhanw-googleef040a72021-05-05 07:17:56 -0700361CircularEventBuffer * EventManagement::GetPriorityBuffer(PriorityLevel aPriority) const
362{
363 CircularEventBuffer * buf = mpEventBuffer;
364 while (!buf->IsFinalDestinationForPriority(aPriority))
365 {
366 buf = buf->GetNextCircularEventBuffer();
367 assert(buf != nullptr);
368 // code guarantees that every PriorityLevel has a buffer destination.
369 }
370 return buf;
371}
372
373CHIP_ERROR EventManagement::CopyAndAdjustDeltaTime(const TLVReader & aReader, size_t aDepth, void * apContext)
374{
yunhanw-googleef040a72021-05-05 07:17:56 -0700375 CopyAndAdjustDeltaTimeContext * ctx = static_cast<CopyAndAdjustDeltaTimeContext *>(apContext);
376 TLVReader reader(aReader);
377
yunhanw-googlee4508322022-01-26 18:27:51 -0800378 if (aReader.GetTag() == TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag))
yunhanw-googleef040a72021-05-05 07:17:56 -0700379 {
yunhanw-googlee4508322022-01-26 18:27:51 -0800380 // Does not go on the wire.
381 return CHIP_NO_ERROR;
382 }
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500383 if ((aReader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kSystemTimestamp)) && !(ctx->mpContext->mFirst) &&
Boris Zbarsky7c77e8e2023-02-23 11:23:27 -0500384 (ctx->mpContext->mCurrentTime.mType == ctx->mpContext->mPreviousTime.mType))
yunhanw-googlee4508322022-01-26 18:27:51 -0800385 {
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500386 return ctx->mpWriter->Put(TLV::ContextTag(EventDataIB::Tag::kDeltaSystemTimestamp),
yunhanw-googlee4508322022-01-26 18:27:51 -0800387 ctx->mpContext->mCurrentTime.mValue - ctx->mpContext->mPreviousTime.mValue);
yunhanw-google9a74bae2021-12-15 13:33:05 -0800388 }
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500389 if ((aReader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kEpochTimestamp)) && !(ctx->mpContext->mFirst) &&
Boris Zbarsky7c77e8e2023-02-23 11:23:27 -0500390 (ctx->mpContext->mCurrentTime.mType == ctx->mpContext->mPreviousTime.mType))
yunhanw-google9a74bae2021-12-15 13:33:05 -0800391 {
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500392 return ctx->mpWriter->Put(TLV::ContextTag(EventDataIB::Tag::kDeltaEpochTimestamp),
yunhanw-googlee4508322022-01-26 18:27:51 -0800393 ctx->mpContext->mCurrentTime.mValue - ctx->mpContext->mPreviousTime.mValue);
yunhanw-googleef040a72021-05-05 07:17:56 -0700394 }
Andrei Litvin1866f462022-04-08 05:21:04 -1000395
396 return ctx->mpWriter->CopyElement(reader);
yunhanw-googleef040a72021-05-05 07:17:56 -0700397}
398
yunhanw-google9a74bae2021-12-15 13:33:05 -0800399void EventManagement::VendEventNumber()
400{
401 CHIP_ERROR err = CHIP_NO_ERROR;
402 // Now advance the counter.
403 err = mpEventNumberCounter->Advance();
404 if (err != CHIP_NO_ERROR)
405 {
406 ChipLogError(EventLogging, "%s Advance() failed with %" CHIP_ERROR_FORMAT, __FUNCTION__, err.Format());
407 }
408
409 // Assign event Number to the buffer's counter's value.
Song GUO0b748ff2022-05-03 17:55:11 +0800410 mLastEventNumber = mpEventNumberCounter->GetValue();
yunhanw-google9a74bae2021-12-15 13:33:05 -0800411}
412
yunhanw-googlef9ce4be2021-12-21 18:27:35 -0800413CHIP_ERROR EventManagement::LogEvent(EventLoggingDelegate * apDelegate, const EventOptions & aEventOptions,
414 EventNumber & aEventNumber)
yunhanw-googleef040a72021-05-05 07:17:56 -0700415{
yunhanw-google86977c22024-02-06 15:39:53 -0800416 assertChipStackLockedByCurrentThread();
yunhanw-googleb8e9ab12022-06-07 23:15:40 -0700417 VerifyOrReturnError(mState != EventManagementStates::Shutdown, CHIP_ERROR_INCORRECT_STATE);
418 return LogEventPrivate(apDelegate, aEventOptions, aEventNumber);
yunhanw-googleef040a72021-05-05 07:17:56 -0700419}
420
yunhanw-googlef9ce4be2021-12-21 18:27:35 -0800421CHIP_ERROR EventManagement::LogEventPrivate(EventLoggingDelegate * apDelegate, const EventOptions & aEventOptions,
yunhanw-googleef040a72021-05-05 07:17:56 -0700422 EventNumber & aEventNumber)
423{
424 CircularTLVWriter writer;
yunhanw-google41700bd2021-12-16 01:20:03 -0800425 CHIP_ERROR err = CHIP_NO_ERROR;
426 uint32_t requestSize = 0;
427 aEventNumber = 0;
428 CircularTLVWriter checkpoint = writer;
yunhanw-google41700bd2021-12-16 01:20:03 -0800429 EventLoadOutContext ctxt = EventLoadOutContext(writer, aEventOptions.mPriority, mLastEventNumber);
yunhanw-google7b7374a2021-12-01 11:08:09 -0800430 EventOptions opts;
Boris Zbarskyaa99d092023-03-03 22:10:46 -0500431
yunhanw-google7b7374a2021-12-01 11:08:09 -0800432 Timestamp timestamp;
Boris Zbarskyaa99d092023-03-03 22:10:46 -0500433#if CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
Boris Zbarsky7c77e8e2023-02-23 11:23:27 -0500434 System::Clock::Milliseconds64 utc_time;
yunhanw-google7b7374a2021-12-01 11:08:09 -0800435 err = System::SystemClock().GetClock_RealTimeMS(utc_time);
Boris Zbarsky7c77e8e2023-02-23 11:23:27 -0500436 if (err == CHIP_NO_ERROR)
437 {
438 timestamp = Timestamp::Epoch(utc_time);
439 }
440 else
Boris Zbarskyaa99d092023-03-03 22:10:46 -0500441#endif // CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
Boris Zbarsky7c77e8e2023-02-23 11:23:27 -0500442 {
443 auto systemTimeMs = System::SystemClock().GetMonotonicMilliseconds64() - mMonotonicStartupTime;
444 timestamp = Timestamp::System(systemTimeMs);
445 }
yunhanw-google7b7374a2021-12-01 11:08:09 -0800446
447 opts = EventOptions(timestamp);
yunhanw-googleef040a72021-05-05 07:17:56 -0700448 // Start the event container (anonymous structure) in the circular buffer
449 writer.Init(*mpEventBuffer);
yunhanw-googleef040a72021-05-05 07:17:56 -0700450
yunhanw-googleee3df3f2021-12-06 16:20:44 -0800451 opts.mPriority = aEventOptions.mPriority;
yunhanw-googleef040a72021-05-05 07:17:56 -0700452 // Create all event specific data
453 // Timestamp; encoded as a delta time
yunhanw-googleef040a72021-05-05 07:17:56 -0700454
yunhanw-googlee4508322022-01-26 18:27:51 -0800455 opts.mPath = aEventOptions.mPath;
456 opts.mFabricIndex = aEventOptions.mFabricIndex;
yunhanw-googleef040a72021-05-05 07:17:56 -0700457
yunhanw-google9a74bae2021-12-15 13:33:05 -0800458 ctxt.mCurrentEventNumber = mLastEventNumber;
459 ctxt.mCurrentTime.mValue = mLastEventTimestamp.mValue;
yunhanw-googleef040a72021-05-05 07:17:56 -0700460
461 err = CalculateEventSize(apDelegate, &opts, requestSize);
462 SuccessOrExit(err);
463
464 // Ensure we have space in the in-memory logging queues
Boris Zbarskyb236bfb2023-02-23 11:51:11 -0500465 err = EnsureSpaceInCircularBuffer(requestSize, aEventOptions.mPriority);
yunhanw-googleef040a72021-05-05 07:17:56 -0700466 SuccessOrExit(err);
467
468 err = ConstructEvent(&ctxt, apDelegate, &opts);
469 SuccessOrExit(err);
470
yunhanw-googleef040a72021-05-05 07:17:56 -0700471 mBytesWritten += writer.GetLengthWritten();
472
473exit:
yunhanw-googleef040a72021-05-05 07:17:56 -0700474 if (err != CHIP_NO_ERROR)
475 {
Damian Królik5e9d4132022-06-27 09:02:15 +0200476 ChipLogError(EventLogging, "Log event with error %" CHIP_ERROR_FORMAT, err.Format());
yunhanw-google41700bd2021-12-16 01:20:03 -0800477 writer = checkpoint;
yunhanw-googleef040a72021-05-05 07:17:56 -0700478 }
yunhanw-googleee3df3f2021-12-06 16:20:44 -0800479 else if (opts.mPriority >= CHIP_CONFIG_EVENT_GLOBAL_PRIORITY)
yunhanw-googleef040a72021-05-05 07:17:56 -0700480 {
yunhanw-google9a74bae2021-12-15 13:33:05 -0800481 aEventNumber = mLastEventNumber;
482 VendEventNumber();
483 mLastEventTimestamp = timestamp;
yunhanw-googleef040a72021-05-05 07:17:56 -0700484#if CHIP_CONFIG_EVENT_LOGGING_VERBOSE_DEBUG_LOGS
Boris Zbarsky0bca2922021-06-10 11:23:46 -0400485 ChipLogDetail(EventLogging,
andrei-menzopol57471cb2022-04-20 23:31:17 +0300486 "LogEvent event number: 0x" ChipLogFormatX64 " priority: %u, endpoint id: 0x%x"
yunhanw-google6f89b9b2021-12-07 14:26:21 -0800487 " cluster id: " ChipLogFormatMEI " event id: 0x%" PRIx32 " %s timestamp: 0x" ChipLogFormatX64,
488 ChipLogValueX64(aEventNumber), static_cast<unsigned>(opts.mPriority), opts.mPath.mEndpointId,
489 ChipLogValueMEI(opts.mPath.mClusterId), opts.mPath.mEventId,
490 opts.mTimestamp.mType == Timestamp::Type::kSystem ? "Sys" : "Epoch", ChipLogValueX64(opts.mTimestamp.mValue));
yunhanw-googleef040a72021-05-05 07:17:56 -0700491#endif // CHIP_CONFIG_EVENT_LOGGING_VERBOSE_DEBUG_LOGS
492
yunhanw-googlecd44f9b2022-03-09 10:36:31 -0800493 err = InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleEventDelivery(opts.mPath, mBytesWritten);
yunhanw-googleef040a72021-05-05 07:17:56 -0700494 }
495
496 return err;
497}
498
499CHIP_ERROR EventManagement::CopyEvent(const TLVReader & aReader, TLVWriter & aWriter, EventLoadOutContext * apContext)
500{
501 TLVReader reader;
502 TLVType containerType;
yunhanw-google3bec0f92021-11-03 16:12:39 -0700503 TLVType containerType1;
yunhanw-googleef040a72021-05-05 07:17:56 -0700504 CopyAndAdjustDeltaTimeContext context(&aWriter, apContext);
505 CHIP_ERROR err = CHIP_NO_ERROR;
506
507 reader.Init(aReader);
yunhanw-google3bec0f92021-11-03 16:12:39 -0700508 ReturnErrorOnFailure(reader.EnterContainer(containerType));
Boris Zbarsky5c096ec2021-12-23 13:28:39 -0500509 ReturnErrorOnFailure(aWriter.StartContainer(AnonymousTag(), kTLVType_Structure, containerType));
yunhanw-googleef040a72021-05-05 07:17:56 -0700510
yunhanw-google3bec0f92021-11-03 16:12:39 -0700511 ReturnErrorOnFailure(reader.Next());
512 ReturnErrorOnFailure(reader.EnterContainer(containerType1));
yunhanw-google3bec0f92021-11-03 16:12:39 -0700513 ReturnErrorOnFailure(
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500514 aWriter.StartContainer(TLV::ContextTag(EventReportIB::Tag::kEventData), kTLVType_Structure, containerType1));
yunhanw-googleef040a72021-05-05 07:17:56 -0700515 err = TLV::Utilities::Iterate(reader, CopyAndAdjustDeltaTime, &context, false /*recurse*/);
516 if (err == CHIP_END_OF_TLV)
517 {
518 err = CHIP_NO_ERROR;
519 }
yunhanw-google3bec0f92021-11-03 16:12:39 -0700520 ReturnErrorOnFailure(err);
521 ReturnErrorOnFailure(aWriter.EndContainer(containerType1));
522 ReturnErrorOnFailure(aWriter.EndContainer(containerType));
523 ReturnErrorOnFailure(aWriter.Finalize());
524 return CHIP_NO_ERROR;
yunhanw-googleef040a72021-05-05 07:17:56 -0700525}
526
Song GUO1ccc2af2022-03-03 01:53:33 +0800527CHIP_ERROR EventManagement::CheckEventContext(EventLoadOutContext * eventLoadOutContext,
528 const EventManagement::EventEnvelopeContext & event)
yunhanw-googled96d8a32021-05-26 18:24:44 -0700529{
yunhanw-googled96d8a32021-05-26 18:24:44 -0700530 if (eventLoadOutContext->mCurrentEventNumber < eventLoadOutContext->mStartingEventNumber)
531 {
Song GUO1ccc2af2022-03-03 01:53:33 +0800532 return CHIP_ERROR_UNEXPECTED_EVENT;
yunhanw-googled96d8a32021-05-26 18:24:44 -0700533 }
yunhanw-googlee4508322022-01-26 18:27:51 -0800534
yunhanw-googlec438b892022-05-05 09:31:07 -0700535 if (event.mFabricIndex.HasValue() &&
536 (event.mFabricIndex.Value() == kUndefinedFabricIndex ||
537 eventLoadOutContext->mSubjectDescriptor.fabricIndex != event.mFabricIndex.Value()))
yunhanw-googlee4508322022-01-26 18:27:51 -0800538 {
Song GUO1ccc2af2022-03-03 01:53:33 +0800539 return CHIP_ERROR_UNEXPECTED_EVENT;
yunhanw-googlee4508322022-01-26 18:27:51 -0800540 }
541
yunhanw-googlec79b67b2021-11-24 20:58:19 -0800542 ConcreteEventPath path(event.mEndpointId, event.mClusterId, event.mEventId);
Song GUO1ccc2af2022-03-03 01:53:33 +0800543 CHIP_ERROR ret = CHIP_ERROR_UNEXPECTED_EVENT;
544
yunhanw-googlec79b67b2021-11-24 20:58:19 -0800545 for (auto * interestedPath = eventLoadOutContext->mpInterestedEventPaths; interestedPath != nullptr;
546 interestedPath = interestedPath->mpNext)
yunhanw-googled96d8a32021-05-26 18:24:44 -0700547 {
yunhanw-google07fc8cd2022-03-24 01:41:28 -0700548 if (interestedPath->mValue.IsEventPathSupersetOf(path))
yunhanw-googled96d8a32021-05-26 18:24:44 -0700549 {
Song GUO1ccc2af2022-03-03 01:53:33 +0800550 ret = CHIP_NO_ERROR;
yunhanw-google19cc9e72022-07-29 07:38:21 -0700551 break;
yunhanw-googled96d8a32021-05-26 18:24:44 -0700552 }
yunhanw-googled96d8a32021-05-26 18:24:44 -0700553 }
Song GUO1ccc2af2022-03-03 01:53:33 +0800554
555 ReturnErrorOnFailure(ret);
556
Thomas Lea5ad899a2024-08-09 13:01:55 -0500557 Access::RequestPath requestPath{ .cluster = event.mClusterId,
558 .endpoint = event.mEndpointId,
Thomas Lea87f62772024-08-27 13:27:10 -0500559 .requestType = Access::RequestType::kEventReadRequest,
Thomas Lea5ad899a2024-08-09 13:01:55 -0500560 .entityId = event.mEventId };
Song GUO1ccc2af2022-03-03 01:53:33 +0800561 Access::Privilege requestPrivilege = RequiredPrivilege::ForReadEvent(path);
562 CHIP_ERROR accessControlError =
563 Access::GetAccessControl().Check(eventLoadOutContext->mSubjectDescriptor, requestPath, requestPrivilege);
Song GUO1ccc2af2022-03-03 01:53:33 +0800564 if (accessControlError != CHIP_NO_ERROR)
565 {
Thomas Lea401a2a02024-08-29 13:06:01 -0500566 ReturnErrorCodeIf((accessControlError != CHIP_ERROR_ACCESS_DENIED) &&
567 (accessControlError != CHIP_ERROR_ACCESS_RESTRICTED_BY_ARL),
568 accessControlError);
yunhanw-google19cc9e72022-07-29 07:38:21 -0700569 ret = CHIP_ERROR_UNEXPECTED_EVENT;
Song GUO1ccc2af2022-03-03 01:53:33 +0800570 }
571
572 return ret;
yunhanw-googled96d8a32021-05-26 18:24:44 -0700573}
574
Song GUO1ccc2af2022-03-03 01:53:33 +0800575CHIP_ERROR EventManagement::EventIterator(const TLVReader & aReader, size_t aDepth, EventLoadOutContext * apEventLoadOutContext,
576 EventEnvelopeContext * event)
yunhanw-googleef040a72021-05-05 07:17:56 -0700577{
578 CHIP_ERROR err = CHIP_NO_ERROR;
579 TLVReader innerReader;
580 TLVType tlvType;
yunhanw-google3bec0f92021-11-03 16:12:39 -0700581 TLVType tlvType1;
yunhanw-googleef040a72021-05-05 07:17:56 -0700582
583 innerReader.Init(aReader);
Song GUO1ccc2af2022-03-03 01:53:33 +0800584 VerifyOrDie(event != nullptr);
yunhanw-googled96d8a32021-05-26 18:24:44 -0700585 ReturnErrorOnFailure(innerReader.EnterContainer(tlvType));
yunhanw-google3bec0f92021-11-03 16:12:39 -0700586 ReturnErrorOnFailure(innerReader.Next());
yunhanw-googlef3d6b7c2021-11-17 13:42:38 -0800587
yunhanw-google3bec0f92021-11-03 16:12:39 -0700588 ReturnErrorOnFailure(innerReader.EnterContainer(tlvType1));
Song GUO1ccc2af2022-03-03 01:53:33 +0800589 err = TLV::Utilities::Iterate(innerReader, FetchEventParameters, event, false /*recurse*/);
yunhanw-google7b7374a2021-12-01 11:08:09 -0800590
Song GUO1ccc2af2022-03-03 01:53:33 +0800591 if (event->mFieldsToRead != kRequiredEventField)
yunhanw-googled96d8a32021-05-26 18:24:44 -0700592 {
593 return CHIP_ERROR_INVALID_ARGUMENT;
594 }
yunhanw-googleef040a72021-05-05 07:17:56 -0700595
596 if (err == CHIP_END_OF_TLV)
597 {
598 err = CHIP_NO_ERROR;
599 }
yunhanw-googled96d8a32021-05-26 18:24:44 -0700600 ReturnErrorOnFailure(err);
yunhanw-googleef040a72021-05-05 07:17:56 -0700601
Song GUO1ccc2af2022-03-03 01:53:33 +0800602 apEventLoadOutContext->mCurrentTime = event->mCurrentTime;
603 apEventLoadOutContext->mCurrentEventNumber = event->mEventNumber;
604
605 err = CheckEventContext(apEventLoadOutContext, *event);
606 if (err == CHIP_NO_ERROR)
yunhanw-googleef040a72021-05-05 07:17:56 -0700607 {
Song GUO1ccc2af2022-03-03 01:53:33 +0800608 err = CHIP_EVENT_ID_FOUND;
609 }
610 else if (err == CHIP_ERROR_UNEXPECTED_EVENT)
611 {
612 err = CHIP_NO_ERROR;
yunhanw-googleef040a72021-05-05 07:17:56 -0700613 }
yunhanw-google9a74bae2021-12-15 13:33:05 -0800614
Song GUO1ccc2af2022-03-03 01:53:33 +0800615 return err;
yunhanw-googleef040a72021-05-05 07:17:56 -0700616}
617
618CHIP_ERROR EventManagement::CopyEventsSince(const TLVReader & aReader, size_t aDepth, void * apContext)
619{
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400620 EventLoadOutContext * const loadOutContext = static_cast<EventLoadOutContext *>(apContext);
Song GUO1ccc2af2022-03-03 01:53:33 +0800621 EventEnvelopeContext event;
622 CHIP_ERROR err = EventIterator(aReader, aDepth, loadOutContext, &event);
yunhanw-googleef040a72021-05-05 07:17:56 -0700623 if (err == CHIP_EVENT_ID_FOUND)
624 {
625 // checkpoint the writer
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400626 TLV::TLVWriter checkpoint = loadOutContext->mWriter;
yunhanw-googleef040a72021-05-05 07:17:56 -0700627
628 err = CopyEvent(aReader, loadOutContext->mWriter, loadOutContext);
629
630 // CHIP_NO_ERROR and CHIP_END_OF_TLV signify a
631 // successful copy. In all other cases, roll back the
632 // writer state back to the checkpoint, i.e., the state
633 // before we began the copy operation.
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400634 if ((err != CHIP_NO_ERROR) && (err != CHIP_END_OF_TLV))
635 {
636 loadOutContext->mWriter = checkpoint;
637 return err;
638 }
yunhanw-googleef040a72021-05-05 07:17:56 -0700639
yunhanw-google7b7374a2021-12-01 11:08:09 -0800640 loadOutContext->mPreviousTime.mValue = loadOutContext->mCurrentTime.mValue;
641 loadOutContext->mFirst = false;
yunhanw-google289ec6e2021-07-19 13:51:47 -0700642 loadOutContext->mEventCount++;
yunhanw-googleef040a72021-05-05 07:17:56 -0700643 }
yunhanw-googleef040a72021-05-05 07:17:56 -0700644 return err;
645}
646
Andrei Litvina3d0a862024-02-20 04:56:48 -0500647CHIP_ERROR EventManagement::FetchEventsSince(TLVWriter & aWriter, const SingleLinkedListNode<EventPathParams> * apEventPathList,
yunhanw-google07fc8cd2022-03-24 01:41:28 -0700648 EventNumber & aEventMin, size_t & aEventCount,
649 const Access::SubjectDescriptor & aSubjectDescriptor)
yunhanw-googleef040a72021-05-05 07:17:56 -0700650{
yunhanw-google8ddfb872021-05-07 18:13:15 -0700651 // TODO: Add particular set of event Paths in FetchEventsSince so that we can filter the interested paths
yunhanw-googleef040a72021-05-05 07:17:56 -0700652 CHIP_ERROR err = CHIP_NO_ERROR;
653 const bool recurse = false;
654 TLVReader reader;
655 CircularEventBufferWrapper bufWrapper;
yunhanw-google9a74bae2021-12-15 13:33:05 -0800656 EventLoadOutContext context(aWriter, PriorityLevel::Invalid, aEventMin);
yunhanw-googleef040a72021-05-05 07:17:56 -0700657
Song GUO1ccc2af2022-03-03 01:53:33 +0800658 context.mSubjectDescriptor = aSubjectDescriptor;
yunhanw-google07fc8cd2022-03-24 01:41:28 -0700659 context.mpInterestedEventPaths = apEventPathList;
yunhanw-google9a74bae2021-12-15 13:33:05 -0800660 err = GetEventReader(reader, PriorityLevel::Critical, &bufWrapper);
yunhanw-googleef040a72021-05-05 07:17:56 -0700661 SuccessOrExit(err);
662
663 err = TLV::Utilities::Iterate(reader, CopyEventsSince, &context, recurse);
664 if (err == CHIP_END_OF_TLV)
665 {
666 err = CHIP_NO_ERROR;
667 }
668
669exit:
Song GUO74beee22022-03-29 23:42:30 +0800670 if (err == CHIP_ERROR_BUFFER_TOO_SMALL || err == CHIP_ERROR_NO_MEMORY)
671 {
672 // We failed to fetch the current event because the buffer is too small, we will start from this one the next time.
673 aEventMin = context.mCurrentEventNumber;
674 }
675 else
676 {
677 // For all other cases, continue from the next event.
678 aEventMin = context.mCurrentEventNumber + 1;
679 }
yunhanw-google289ec6e2021-07-19 13:51:47 -0700680 aEventCount += context.mEventCount;
yunhanw-googleef040a72021-05-05 07:17:56 -0700681 return err;
682}
683
yunhanw-googlec438b892022-05-05 09:31:07 -0700684CHIP_ERROR EventManagement::FabricRemovedCB(const TLV::TLVReader & aReader, size_t aDepth, void * apContext)
685{
686 // the function does not actually remove the event, instead, it sets the fabric index to an invalid value.
687 FabricIndex * invalidFabricIndex = static_cast<FabricIndex *>(apContext);
688
689 TLVReader event;
690 TLVType tlvType;
691 TLVType tlvType1;
692 event.Init(aReader);
693 VerifyOrReturnError(event.EnterContainer(tlvType) == CHIP_NO_ERROR, CHIP_NO_ERROR);
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500694 VerifyOrReturnError(event.Next(TLV::ContextTag(EventReportIB::Tag::kEventData)) == CHIP_NO_ERROR, CHIP_NO_ERROR);
yunhanw-googlec438b892022-05-05 09:31:07 -0700695 VerifyOrReturnError(event.EnterContainer(tlvType1) == CHIP_NO_ERROR, CHIP_NO_ERROR);
696
697 while (CHIP_NO_ERROR == event.Next())
698 {
699 if (event.GetTag() == TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag))
700 {
701 uint8_t fabricIndex = 0;
702 VerifyOrReturnError(event.Get(fabricIndex) == CHIP_NO_ERROR, CHIP_NO_ERROR);
703 if (fabricIndex == *invalidFabricIndex)
704 {
Martin Turon77d84e42023-01-13 06:58:22 -0800705 TLVCircularBuffer * readBuffer = static_cast<TLVCircularBuffer *>(event.GetBackingStore());
yunhanw-googlec438b892022-05-05 09:31:07 -0700706 // fabricIndex is encoded as an integer; the dataPtr will point to a location immediately after its encoding
707 // shift the dataPtr to point to the encoding of the fabric index, accounting for wraparound in backing storage
708 // we cannot get the actual encoding size from current container beginning to the fabric index because of several
709 // optional parameters, so we are assuming minimal encoding is used and the fabric index is 1 byte.
710 uint8_t * dataPtr;
711 if (event.GetReadPoint() != readBuffer->GetQueue())
712 {
713 dataPtr = readBuffer->GetQueue() + (event.GetReadPoint() - readBuffer->GetQueue() - 1);
714 }
715 else
716 {
717 dataPtr = readBuffer->GetQueue() + readBuffer->GetTotalDataLength() - 1;
718 }
719
720 *dataPtr = kUndefinedFabricIndex;
721 }
722 return CHIP_NO_ERROR;
723 }
724 }
725 return CHIP_NO_ERROR;
726}
727
728CHIP_ERROR EventManagement::FabricRemoved(FabricIndex aFabricIndex)
729{
730 const bool recurse = false;
731 TLVReader reader;
732 CircularEventBufferWrapper bufWrapper;
733
yunhanw-googlec438b892022-05-05 09:31:07 -0700734 ReturnErrorOnFailure(GetEventReader(reader, PriorityLevel::Critical, &bufWrapper));
735 CHIP_ERROR err = TLV::Utilities::Iterate(reader, FabricRemovedCB, &aFabricIndex, recurse);
736 if (err == CHIP_END_OF_TLV)
737 {
738 err = CHIP_NO_ERROR;
739 }
740 return err;
741}
742
yunhanw-googleef040a72021-05-05 07:17:56 -0700743CHIP_ERROR EventManagement::GetEventReader(TLVReader & aReader, PriorityLevel aPriority, CircularEventBufferWrapper * apBufWrapper)
744{
yunhanw-googleef040a72021-05-05 07:17:56 -0700745 CircularEventBuffer * buffer = GetPriorityBuffer(aPriority);
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400746 VerifyOrReturnError(buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
yunhanw-googleef040a72021-05-05 07:17:56 -0700747 apBufWrapper->mpCurrent = buffer;
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400748
749 CircularEventReader reader;
yunhanw-googleef040a72021-05-05 07:17:56 -0700750 reader.Init(apBufWrapper);
751 aReader.Init(reader);
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400752
753 return CHIP_NO_ERROR;
yunhanw-googleef040a72021-05-05 07:17:56 -0700754}
755
yunhanw-googlec438b892022-05-05 09:31:07 -0700756CHIP_ERROR EventManagement::FetchEventParameters(const TLVReader & aReader, size_t, void * apContext)
yunhanw-googleef040a72021-05-05 07:17:56 -0700757{
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400758 EventEnvelopeContext * const envelope = static_cast<EventEnvelopeContext *>(apContext);
yunhanw-googleef040a72021-05-05 07:17:56 -0700759 TLVReader reader;
yunhanw-googleef040a72021-05-05 07:17:56 -0700760 reader.Init(aReader);
761
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500762 if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kPath))
yunhanw-googled96d8a32021-05-26 18:24:44 -0700763 {
yunhanw-google2fe90242021-11-01 15:13:44 -0700764 EventPathIB::Parser path;
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400765 ReturnErrorOnFailure(path.Init(aReader));
yunhanw-google1f6c6e62021-11-02 10:09:53 -0700766 ReturnErrorOnFailure(path.GetEndpoint(&(envelope->mEndpointId)));
767 ReturnErrorOnFailure(path.GetCluster(&(envelope->mClusterId)));
768 ReturnErrorOnFailure(path.GetEvent(&(envelope->mEventId)));
yunhanw-google3bec0f92021-11-03 16:12:39 -0700769 envelope->mFieldsToRead |= 1 << to_underlying(EventDataIB::Tag::kPath);
yunhanw-googled96d8a32021-05-26 18:24:44 -0700770 }
771
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500772 if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kPriority))
yunhanw-googleef040a72021-05-05 07:17:56 -0700773 {
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400774 uint16_t extPriority; // Note: the type here matches the type case in EventManagement::LogEvent, priority section
775 ReturnErrorOnFailure(reader.Get(extPriority));
yunhanw-googleef040a72021-05-05 07:17:56 -0700776 envelope->mPriority = static_cast<PriorityLevel>(extPriority);
yunhanw-google3bec0f92021-11-03 16:12:39 -0700777 envelope->mFieldsToRead |= 1 << to_underlying(EventDataIB::Tag::kPriority);
yunhanw-googleef040a72021-05-05 07:17:56 -0700778 }
779
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500780 if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kEventNumber))
yunhanw-google83aac592021-12-09 23:14:55 -0800781 {
yunhanw-google9a74bae2021-12-15 13:33:05 -0800782 ReturnErrorOnFailure(reader.Get(envelope->mEventNumber));
yunhanw-google83aac592021-12-09 23:14:55 -0800783 }
784
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500785 if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kSystemTimestamp))
yunhanw-google83aac592021-12-09 23:14:55 -0800786 {
yunhanw-google9a74bae2021-12-15 13:33:05 -0800787 uint64_t systemTime;
788 ReturnErrorOnFailure(reader.Get(systemTime));
789 envelope->mCurrentTime.mType = Timestamp::Type::kSystem;
790 envelope->mCurrentTime.mValue = systemTime;
791 }
792
Boris Zbarskye434c6a2023-03-01 12:35:37 -0500793 if (reader.GetTag() == TLV::ContextTag(EventDataIB::Tag::kEpochTimestamp))
yunhanw-google9a74bae2021-12-15 13:33:05 -0800794 {
795 uint64_t epochTime;
796 ReturnErrorOnFailure(reader.Get(epochTime));
797 envelope->mCurrentTime.mType = Timestamp::Type::kEpoch;
798 envelope->mCurrentTime.mValue = epochTime;
yunhanw-google83aac592021-12-09 23:14:55 -0800799 }
yunhanw-googlee4508322022-01-26 18:27:51 -0800800
801 if (reader.GetTag() == TLV::ProfileTag(kEventManagementProfile, kFabricIndexTag))
802 {
yunhanw-googlec438b892022-05-05 09:31:07 -0700803 uint8_t fabricIndex = kUndefinedFabricIndex;
804 ReturnErrorOnFailure(reader.Get(fabricIndex));
805 envelope->mFabricIndex.SetValue(fabricIndex);
yunhanw-googlee4508322022-01-26 18:27:51 -0800806 }
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400807 return CHIP_NO_ERROR;
yunhanw-googleef040a72021-05-05 07:17:56 -0700808}
809
Martin Turon77d84e42023-01-13 06:58:22 -0800810CHIP_ERROR EventManagement::EvictEvent(TLVCircularBuffer & apBuffer, void * apAppData, TLVReader & aReader)
yunhanw-googleef040a72021-05-05 07:17:56 -0700811{
yunhanw-googleef040a72021-05-05 07:17:56 -0700812 // pull out the delta time, pull out the priority
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400813 ReturnErrorOnFailure(aReader.Next());
yunhanw-googleef040a72021-05-05 07:17:56 -0700814
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400815 TLVType containerType;
yunhanw-google3bec0f92021-11-03 16:12:39 -0700816 TLVType containerType1;
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400817 ReturnErrorOnFailure(aReader.EnterContainer(containerType));
yunhanw-google3bec0f92021-11-03 16:12:39 -0700818 ReturnErrorOnFailure(aReader.Next());
yunhanw-googlef3d6b7c2021-11-17 13:42:38 -0800819
yunhanw-google3bec0f92021-11-03 16:12:39 -0700820 ReturnErrorOnFailure(aReader.EnterContainer(containerType1));
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400821 EventEnvelopeContext context;
822 constexpr bool recurse = false;
823 CHIP_ERROR err = TLV::Utilities::Iterate(aReader, FetchEventParameters, &context, recurse);
yunhanw-googleef040a72021-05-05 07:17:56 -0700824 if (err == CHIP_END_OF_TLV)
825 {
826 err = CHIP_NO_ERROR;
827 }
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400828 ReturnErrorOnFailure(err);
yunhanw-googleef040a72021-05-05 07:17:56 -0700829
yunhanw-google3bec0f92021-11-03 16:12:39 -0700830 ReturnErrorOnFailure(aReader.ExitContainer(containerType1));
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400831 ReturnErrorOnFailure(aReader.ExitContainer(containerType));
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400832 const PriorityLevel imp = static_cast<PriorityLevel>(context.mPriority);
yunhanw-googleef040a72021-05-05 07:17:56 -0700833
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400834 ReclaimEventCtx * const ctx = static_cast<ReclaimEventCtx *>(apAppData);
835 CircularEventBuffer * const eventBuffer = ctx->mpEventBuffer;
yunhanw-googleef040a72021-05-05 07:17:56 -0700836 if (eventBuffer->IsFinalDestinationForPriority(imp))
837 {
yunhanw-google9a74bae2021-12-15 13:33:05 -0800838 ChipLogProgress(EventLogging,
839 "Dropped 1 event from buffer with priority %u and event number 0x" ChipLogFormatX64
840 " due to overflow: event priority_level: %u",
841 static_cast<unsigned>(eventBuffer->GetPriority()), ChipLogValueX64(context.mEventNumber),
842 static_cast<unsigned>(imp));
yunhanw-googleef040a72021-05-05 07:17:56 -0700843 ctx->mSpaceNeededForMovedEvent = 0;
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400844 return CHIP_NO_ERROR;
yunhanw-googleef040a72021-05-05 07:17:56 -0700845 }
846
Kevin Schoedelf9550e12021-06-21 17:08:48 -0400847 // event is not getting dropped. Note how much space it requires, and return.
848 ctx->mSpaceNeededForMovedEvent = aReader.GetLengthRead();
849 return CHIP_END_OF_TLV;
yunhanw-googleef040a72021-05-05 07:17:56 -0700850}
851
Andrei Litvind43e6a72022-03-17 17:39:24 -0400852void EventManagement::SetScheduledEventInfo(EventNumber & aEventNumber, uint32_t & aInitialWrittenEventBytes) const
yunhanw-google8ddfb872021-05-07 18:13:15 -0700853{
yunhanw-google41700bd2021-12-16 01:20:03 -0800854 aEventNumber = mLastEventNumber;
855 aInitialWrittenEventBytes = mBytesWritten;
yunhanw-google8ddfb872021-05-07 18:13:15 -0700856}
857
Andrei Litvin0b8ffb72024-09-18 14:53:18 -0400858CHIP_ERROR EventManagement::GenerateEvent(EventLoggingDelegate * eventPayloadWriter, const EventOptions & options,
859 EventNumber & generatedEventNumber)
860{
861 return LogEvent(eventPayloadWriter, options, generatedEventNumber);
862}
863
yunhanw-googleef040a72021-05-05 07:17:56 -0700864void CircularEventBuffer::Init(uint8_t * apBuffer, uint32_t aBufferLength, CircularEventBuffer * apPrev,
865 CircularEventBuffer * apNext, PriorityLevel aPriorityLevel)
866{
Martin Turon77d84e42023-01-13 06:58:22 -0800867 TLVCircularBuffer::Init(apBuffer, aBufferLength);
Boris Zbarskycc3a98c2022-04-14 23:15:16 -0400868 mpPrev = apPrev;
869 mpNext = apNext;
870 mPriority = aPriorityLevel;
yunhanw-googleef040a72021-05-05 07:17:56 -0700871}
872
873bool CircularEventBuffer::IsFinalDestinationForPriority(PriorityLevel aPriority) const
874{
875 return !((mpNext != nullptr) && (mpNext->mPriority <= aPriority));
876}
877
yunhanw-google015f11c2023-02-22 15:28:07 -0800878/**
879 * @brief
880 * TLVCircularBuffer::OnInit can modify the state of the buffer, but we don't want that behavior here.
881 * We want to make sure we don't change our state, and just report the currently-available space.
882 */
883CHIP_ERROR CircularEventBuffer::OnInit(TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen)
884{
885 GetCurrentWritableBuffer(bufStart, bufLen);
886 return CHIP_NO_ERROR;
887}
888
yunhanw-googleef040a72021-05-05 07:17:56 -0700889void CircularEventReader::Init(CircularEventBufferWrapper * apBufWrapper)
890{
891 CircularEventBuffer * prev;
892
893 if (apBufWrapper->mpCurrent == nullptr)
894 return;
895
896 TLVReader::Init(*apBufWrapper, apBufWrapper->mpCurrent->DataLength());
897 mMaxLen = apBufWrapper->mpCurrent->DataLength();
898 for (prev = apBufWrapper->mpCurrent->GetPreviousCircularEventBuffer(); prev != nullptr;
899 prev = prev->GetPreviousCircularEventBuffer())
900 {
901 CircularEventBufferWrapper bufWrapper;
902 bufWrapper.mpCurrent = prev;
903 mMaxLen += prev->DataLength();
904 }
905}
906
907CHIP_ERROR CircularEventBufferWrapper::GetNextBuffer(TLVReader & aReader, const uint8_t *& aBufStart, uint32_t & aBufLen)
908{
909 CHIP_ERROR err = CHIP_NO_ERROR;
910 mpCurrent->GetNextBuffer(aReader, aBufStart, aBufLen);
911 SuccessOrExit(err);
912
913 if ((aBufLen == 0) && (mpCurrent->GetPreviousCircularEventBuffer() != nullptr))
914 {
915 mpCurrent = mpCurrent->GetPreviousCircularEventBuffer();
916 aBufStart = nullptr;
917 err = GetNextBuffer(aReader, aBufStart, aBufLen);
918 }
919
920exit:
yunhanw-googleef040a72021-05-05 07:17:56 -0700921 return err;
922}
Andrei Litvin0b8ffb72024-09-18 14:53:18 -0400923
yunhanw-googleef040a72021-05-05 07:17:56 -0700924} // namespace app
925} // namespace chip