1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef CHRE_UTIL_DUPLICATE_MESSAGE_DETECTOR_H_ 18 #define CHRE_UTIL_DUPLICATE_MESSAGE_DETECTOR_H_ 19 20 #include "chre/util/non_copyable.h" 21 #include "chre/util/optional.h" 22 #include "chre/util/priority_queue.h" 23 #include "chre/util/time.h" 24 #include "chre_api/chre.h" 25 26 #include <functional> 27 28 namespace chre { 29 30 /** 31 * This class is used to detect duplicate reliable messages. It keeps a record 32 * of all reliable messages that have been sent from the host. If a message with 33 * the same message sequence number and host endpoint is sent again, it is 34 * considered a duplicate. This class is not thread-safe. 35 * 36 * A typical usage of this class would be as follows: 37 * 38 * Call findOrAdd() to add a new message to the detector. If the message is a 39 * duplicate, the detector will return the error code previously recorded. 40 * If the message is not a duplicate, the detector will return an empty 41 * Optional. 42 * 43 * Call findAndSetError() to set the error code for a message that has already 44 * been added to the detector. 45 * 46 * Call removeOldEntries() to remove any messages that have been in the detector 47 * for longer than the timeout specified in the constructor. 48 */ 49 class DuplicateMessageDetector : public NonCopyable { 50 public: 51 struct ReliableMessageRecord { 52 Nanoseconds timestamp; 53 uint32_t messageSequenceNumber; 54 uint16_t hostEndpoint; 55 Optional<chreError> error; 56 57 inline bool operator>(const ReliableMessageRecord &rhs) const { 58 return timestamp > rhs.timestamp; 59 } 60 }; 61 62 DuplicateMessageDetector() = delete; DuplicateMessageDetector(Nanoseconds timeout)63 DuplicateMessageDetector(Nanoseconds timeout): 64 kTimeout(timeout) {} 65 ~DuplicateMessageDetector() = default; 66 67 //! Finds the message with the given message sequence number and host 68 //! endpoint. If the message is not found, a new message is added to the 69 //! detector. Returns the error code previously recorded for the message, or 70 //! an empty Optional if the message is not a duplicate. If outIsDuplicate is 71 //! not nullptr, it will be set to true if the message is a duplicate (was 72 //! found), or false otherwise. 73 Optional<chreError> findOrAdd(uint32_t messageSequenceNumber, 74 uint16_t hostEndpoint, 75 bool *outIsDuplicate = nullptr); 76 77 //! Sets the error code for a message that has already been added to the 78 //! detector. Returns true if the message was found and the error code was 79 //! set, or false if the message was not found. 80 bool findAndSetError(uint32_t messageSequenceNumber, uint16_t hostEndpoint, 81 chreError error); 82 83 //! Removes any messages that have been in the detector for longer than the 84 //! timeout specified in the constructor. 85 void removeOldEntries(); 86 87 private: 88 //! The timeout specified in the constructor. This should be the reliable 89 //! message timeout. 90 Nanoseconds kTimeout; 91 92 //! The queue of reliable message records. 93 PriorityQueue<ReliableMessageRecord, std::greater<ReliableMessageRecord>> 94 mReliableMessageRecordQueue; 95 96 //! Adds a new message to the detector. Returns the message record, or nullptr 97 //! if the message could not be added. Not thread safe. 98 ReliableMessageRecord *addLocked(uint32_t messageSequenceNumber, 99 uint16_t hostEndpoint); 100 101 //! Finds the message with the given message sequence number and host 102 //! endpoint, else returns nullptr. Not thread safe. If reverse is true, 103 //! this function searches from the end of the queue. 104 ReliableMessageRecord *findLocked(uint32_t messageSequenceNumber, 105 uint16_t hostEndpoint, 106 bool reverse = false); 107 }; 108 109 } // namespace chre 110 111 #endif // CHRE_UTIL_DUPLICATE_MESSAGE_DETECTOR_H_ 112