1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker * Copyright (C) 2024 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker *
4*84e33947SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker *
8*84e33947SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker *
10*84e33947SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker */
16*84e33947SAndroid Build Coastguard Worker
17*84e33947SAndroid Build Coastguard Worker #include "chre/util/duplicate_message_detector.h"
18*84e33947SAndroid Build Coastguard Worker
19*84e33947SAndroid Build Coastguard Worker #include "chre/platform/system_time.h"
20*84e33947SAndroid Build Coastguard Worker
21*84e33947SAndroid Build Coastguard Worker #include <cstdint>
22*84e33947SAndroid Build Coastguard Worker
23*84e33947SAndroid Build Coastguard Worker namespace chre {
24*84e33947SAndroid Build Coastguard Worker
findOrAdd(uint32_t messageSequenceNumber,uint16_t hostEndpoint,bool * outIsDuplicate)25*84e33947SAndroid Build Coastguard Worker Optional<chreError> DuplicateMessageDetector::findOrAdd(
26*84e33947SAndroid Build Coastguard Worker uint32_t messageSequenceNumber, uint16_t hostEndpoint,
27*84e33947SAndroid Build Coastguard Worker bool *outIsDuplicate) {
28*84e33947SAndroid Build Coastguard Worker DuplicateMessageDetector::ReliableMessageRecord *record =
29*84e33947SAndroid Build Coastguard Worker findLocked(messageSequenceNumber, hostEndpoint);
30*84e33947SAndroid Build Coastguard Worker if (outIsDuplicate != nullptr) {
31*84e33947SAndroid Build Coastguard Worker *outIsDuplicate = record != nullptr;
32*84e33947SAndroid Build Coastguard Worker }
33*84e33947SAndroid Build Coastguard Worker
34*84e33947SAndroid Build Coastguard Worker if (record == nullptr) {
35*84e33947SAndroid Build Coastguard Worker record = addLocked(messageSequenceNumber, hostEndpoint);
36*84e33947SAndroid Build Coastguard Worker if (record == nullptr) {
37*84e33947SAndroid Build Coastguard Worker LOG_OOM();
38*84e33947SAndroid Build Coastguard Worker if (outIsDuplicate != nullptr) {
39*84e33947SAndroid Build Coastguard Worker *outIsDuplicate = true;
40*84e33947SAndroid Build Coastguard Worker }
41*84e33947SAndroid Build Coastguard Worker return CHRE_ERROR_NO_MEMORY;
42*84e33947SAndroid Build Coastguard Worker }
43*84e33947SAndroid Build Coastguard Worker }
44*84e33947SAndroid Build Coastguard Worker return record->error;
45*84e33947SAndroid Build Coastguard Worker }
46*84e33947SAndroid Build Coastguard Worker
findAndSetError(uint32_t messageSequenceNumber,uint16_t hostEndpoint,chreError error)47*84e33947SAndroid Build Coastguard Worker bool DuplicateMessageDetector::findAndSetError(uint32_t messageSequenceNumber,
48*84e33947SAndroid Build Coastguard Worker uint16_t hostEndpoint,
49*84e33947SAndroid Build Coastguard Worker chreError error) {
50*84e33947SAndroid Build Coastguard Worker DuplicateMessageDetector::ReliableMessageRecord *record =
51*84e33947SAndroid Build Coastguard Worker findLocked(messageSequenceNumber, hostEndpoint);
52*84e33947SAndroid Build Coastguard Worker if (record == nullptr) {
53*84e33947SAndroid Build Coastguard Worker return false;
54*84e33947SAndroid Build Coastguard Worker }
55*84e33947SAndroid Build Coastguard Worker
56*84e33947SAndroid Build Coastguard Worker record->error = error;
57*84e33947SAndroid Build Coastguard Worker return true;
58*84e33947SAndroid Build Coastguard Worker }
59*84e33947SAndroid Build Coastguard Worker
removeOldEntries()60*84e33947SAndroid Build Coastguard Worker void DuplicateMessageDetector::removeOldEntries() {
61*84e33947SAndroid Build Coastguard Worker Nanoseconds now = SystemTime::getMonotonicTime();
62*84e33947SAndroid Build Coastguard Worker while (!mReliableMessageRecordQueue.empty()) {
63*84e33947SAndroid Build Coastguard Worker ReliableMessageRecord &record = mReliableMessageRecordQueue.top();
64*84e33947SAndroid Build Coastguard Worker if (record.timestamp + kTimeout <= now) {
65*84e33947SAndroid Build Coastguard Worker mReliableMessageRecordQueue.pop();
66*84e33947SAndroid Build Coastguard Worker } else {
67*84e33947SAndroid Build Coastguard Worker break;
68*84e33947SAndroid Build Coastguard Worker }
69*84e33947SAndroid Build Coastguard Worker }
70*84e33947SAndroid Build Coastguard Worker }
71*84e33947SAndroid Build Coastguard Worker
72*84e33947SAndroid Build Coastguard Worker DuplicateMessageDetector::ReliableMessageRecord*
addLocked(uint32_t messageSequenceNumber,uint16_t hostEndpoint)73*84e33947SAndroid Build Coastguard Worker DuplicateMessageDetector::addLocked(
74*84e33947SAndroid Build Coastguard Worker uint32_t messageSequenceNumber,
75*84e33947SAndroid Build Coastguard Worker uint16_t hostEndpoint) {
76*84e33947SAndroid Build Coastguard Worker bool success = mReliableMessageRecordQueue.push(
77*84e33947SAndroid Build Coastguard Worker ReliableMessageRecord{
78*84e33947SAndroid Build Coastguard Worker .timestamp = SystemTime::getMonotonicTime(),
79*84e33947SAndroid Build Coastguard Worker .messageSequenceNumber = messageSequenceNumber,
80*84e33947SAndroid Build Coastguard Worker .hostEndpoint = hostEndpoint,
81*84e33947SAndroid Build Coastguard Worker .error = Optional<chreError>()});
82*84e33947SAndroid Build Coastguard Worker return success
83*84e33947SAndroid Build Coastguard Worker ? findLocked(messageSequenceNumber, hostEndpoint, /* reverse= */ true)
84*84e33947SAndroid Build Coastguard Worker : nullptr;
85*84e33947SAndroid Build Coastguard Worker }
86*84e33947SAndroid Build Coastguard Worker
87*84e33947SAndroid Build Coastguard Worker DuplicateMessageDetector::ReliableMessageRecord*
findLocked(uint32_t messageSequenceNumber,uint16_t hostEndpoint,bool reverse)88*84e33947SAndroid Build Coastguard Worker DuplicateMessageDetector::findLocked(uint32_t messageSequenceNumber,
89*84e33947SAndroid Build Coastguard Worker uint16_t hostEndpoint,
90*84e33947SAndroid Build Coastguard Worker bool reverse) {
91*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < mReliableMessageRecordQueue.size(); ++i) {
92*84e33947SAndroid Build Coastguard Worker size_t index = reverse ? mReliableMessageRecordQueue.size() - i - 1 : i;
93*84e33947SAndroid Build Coastguard Worker ReliableMessageRecord &record = mReliableMessageRecordQueue[index];
94*84e33947SAndroid Build Coastguard Worker if (record.messageSequenceNumber == messageSequenceNumber &&
95*84e33947SAndroid Build Coastguard Worker record.hostEndpoint == hostEndpoint) {
96*84e33947SAndroid Build Coastguard Worker return &record;
97*84e33947SAndroid Build Coastguard Worker }
98*84e33947SAndroid Build Coastguard Worker }
99*84e33947SAndroid Build Coastguard Worker return nullptr;
100*84e33947SAndroid Build Coastguard Worker }
101*84e33947SAndroid Build Coastguard Worker
102*84e33947SAndroid Build Coastguard Worker } // namespace chre
103