/* * Copyright (C) 2024 The Android Open Source Project * * 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. */ #include "chre/util/duplicate_message_detector.h" #include "chre/platform/system_time.h" #include namespace chre { Optional DuplicateMessageDetector::findOrAdd( uint32_t messageSequenceNumber, uint16_t hostEndpoint, bool *outIsDuplicate) { DuplicateMessageDetector::ReliableMessageRecord *record = findLocked(messageSequenceNumber, hostEndpoint); if (outIsDuplicate != nullptr) { *outIsDuplicate = record != nullptr; } if (record == nullptr) { record = addLocked(messageSequenceNumber, hostEndpoint); if (record == nullptr) { LOG_OOM(); if (outIsDuplicate != nullptr) { *outIsDuplicate = true; } return CHRE_ERROR_NO_MEMORY; } } return record->error; } bool DuplicateMessageDetector::findAndSetError(uint32_t messageSequenceNumber, uint16_t hostEndpoint, chreError error) { DuplicateMessageDetector::ReliableMessageRecord *record = findLocked(messageSequenceNumber, hostEndpoint); if (record == nullptr) { return false; } record->error = error; return true; } void DuplicateMessageDetector::removeOldEntries() { Nanoseconds now = SystemTime::getMonotonicTime(); while (!mReliableMessageRecordQueue.empty()) { ReliableMessageRecord &record = mReliableMessageRecordQueue.top(); if (record.timestamp + kTimeout <= now) { mReliableMessageRecordQueue.pop(); } else { break; } } } DuplicateMessageDetector::ReliableMessageRecord* DuplicateMessageDetector::addLocked( uint32_t messageSequenceNumber, uint16_t hostEndpoint) { bool success = mReliableMessageRecordQueue.push( ReliableMessageRecord{ .timestamp = SystemTime::getMonotonicTime(), .messageSequenceNumber = messageSequenceNumber, .hostEndpoint = hostEndpoint, .error = Optional()}); return success ? findLocked(messageSequenceNumber, hostEndpoint, /* reverse= */ true) : nullptr; } DuplicateMessageDetector::ReliableMessageRecord* DuplicateMessageDetector::findLocked(uint32_t messageSequenceNumber, uint16_t hostEndpoint, bool reverse) { for (size_t i = 0; i < mReliableMessageRecordQueue.size(); ++i) { size_t index = reverse ? mReliableMessageRecordQueue.size() - i - 1 : i; ReliableMessageRecord &record = mReliableMessageRecordQueue[index]; if (record.messageSequenceNumber == messageSequenceNumber && record.hostEndpoint == hostEndpoint) { return &record; } } return nullptr; } } // namespace chre