1 /*
2  * Copyright (C) Huawei Device Co., Ltd. 2023-2023. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef LOG_TAG
16 #define LOG_TAG "bt_c_adapter_gatt_utils"
17 #endif
18 
19 #include "ohos_bt_gatt_utils.h"
20 #include "bluetooth_log.h"
21 #include "bluetooth_utils.h"
22 #include <map>
23 #include <queue>
24 #include <mutex>
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 using namespace std;
31 
32 namespace OHOS {
33 namespace Bluetooth {
34 
35 #define MAX_ADV_ADDR_MAP_SIZE 128
36 #define ADV_ADDR_TIMEOUT (60 * 60 * 1000) // 1 hour
37 #define MS_PER_SECOND 1000
38 #define NS_PER_MS 1000000
39 
40 struct CaseInsensitiveCompare {
operator ()OHOS::Bluetooth::CaseInsensitiveCompare41     bool operator()(const string& s1, const string& s2) const
42     {
43         return lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(),
44             [](char c1, char c2) { return tolower(c1) < tolower(c2); });
45     }
46 };
47 static mutex g_mapQueMutex;
48 static map<string, uint64_t, CaseInsensitiveCompare> g_advAddrMap; // map<addr, time>
49 static queue<pair<string, uint64_t>> g_advTimeQueue; // pair<addr, time>
50 
GetBootMillis()51 static uint64_t GetBootMillis()
52 {
53     struct timespec ts = {};
54     clock_gettime(CLOCK_BOOTTIME, &ts);
55     return ts.tv_sec * MS_PER_SECOND + ts.tv_nsec / NS_PER_MS;
56 }
57 
58 /*
59  * The method is only available for {@link BleStartAdvWithAddr}.
60  * Because there cannot be duplicate adv addresses within one hour,
61  * this method will delete adv addresses after one hour.
62  */
RemoveTimeoutAdvAddr()63 void RemoveTimeoutAdvAddr()
64 {
65     lock_guard<mutex> lock(g_mapQueMutex);
66     uint64_t currentMillis = GetBootMillis();
67     while (!g_advTimeQueue.empty() && currentMillis >= g_advTimeQueue.front().second + ADV_ADDR_TIMEOUT) {
68         g_advAddrMap.erase(g_advTimeQueue.front().first);
69         g_advTimeQueue.pop();
70     }
71 }
72 
73 /*
74  * This method is only available for {@link BleStartAdvWithAddr}.
75  * Duplicate addresses within 15 minutes are allowed to be broadcast,
76  * and duplicate addresses after 15 minutes are not allowed to be broadcast.
77  * There is no limit on non-duplicate addresses.
78  */
CanStartAdv(const string & addrStr)79 bool CanStartAdv(const string& addrStr)
80 {
81     lock_guard<mutex> lock(g_mapQueMutex);
82     HILOGI("addr: %{public}s", GetEncryptAddr(addrStr).c_str());
83     uint64_t currentMillis = GetBootMillis();
84     auto addrTime = g_advAddrMap.find(addrStr);
85     if (addrTime != g_advAddrMap.end()) {
86         if (currentMillis >= addrTime->second + ADV_ADDR_TIME_THRESHOLD) {
87             HILOGW("has the same adv addr in [15mins, 60mins]: %{public}s", GetEncryptAddr(addrStr).c_str());
88             return false;
89         } else {
90             return true;
91         }
92     }
93     if (g_advTimeQueue.size() >= MAX_ADV_ADDR_MAP_SIZE) {
94         g_advAddrMap.erase(g_advTimeQueue.front().first);
95         g_advTimeQueue.pop();
96     }
97     g_advTimeQueue.push(pair<string, uint64_t>(addrStr, currentMillis));
98     g_advAddrMap.insert(make_pair(addrStr, currentMillis));
99     return true;
100 }
101 
102 }  // namespace Bluetooth
103 }  // namespace OHOS
104 #ifdef __cplusplus
105 }
106 #endif