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
16 #include "ohos_bt_gatt_utils.h"
17 #include "bluetooth_log.h"
18 #include "bluetooth_utils.h"
19 #include <map>
20 #include <queue>
21 #include <mutex>
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 using namespace std;
28
29 namespace OHOS {
30 namespace Bluetooth {
31
32 #define MAX_ADV_ADDR_MAP_SIZE 128
33 #define ADV_ADDR_TIMEOUT (60 * 60 * 1000) // 1 hour
34 #define MS_PER_SECOND 1000
35 #define NS_PER_MS 1000000
36
37 struct CaseInsensitiveCompare {
operator ()OHOS::Bluetooth::CaseInsensitiveCompare38 bool operator()(const string& s1, const string& s2) const
39 {
40 return lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(),
41 [](char c1, char c2) { return tolower(c1) < tolower(c2); });
42 }
43 };
44 static mutex g_mapQueMutex;
45 static map<string, uint64_t, CaseInsensitiveCompare> g_advAddrMap; // map<addr, time>
46 static queue<pair<string, uint64_t>> g_advTimeQueue; // pair<addr, time>
47
GetBootMillis()48 static uint64_t GetBootMillis()
49 {
50 struct timespec ts = {};
51 clock_gettime(CLOCK_BOOTTIME, &ts);
52 return ts.tv_sec * MS_PER_SECOND + ts.tv_nsec / NS_PER_MS;
53 }
54
55 /*
56 * The method is only available for {@link BleStartAdvWithAddr}.
57 * Because there cannot be duplicate adv addresses within one hour,
58 * this method will delete adv addresses after one hour.
59 */
RemoveTimeoutAdvAddr()60 void RemoveTimeoutAdvAddr()
61 {
62 lock_guard<mutex> lock(g_mapQueMutex);
63 uint64_t currentMillis = GetBootMillis();
64 while (!g_advTimeQueue.empty() && currentMillis >= g_advTimeQueue.front().second + ADV_ADDR_TIMEOUT) {
65 g_advAddrMap.erase(g_advTimeQueue.front().first);
66 g_advTimeQueue.pop();
67 }
68 }
69
70 /*
71 * This method is only available for {@link BleStartAdvWithAddr}.
72 * Duplicate addresses within 15 minutes are allowed to be broadcast,
73 * and duplicate addresses after 15 minutes are not allowed to be broadcast.
74 * There is no limit on non-duplicate addresses.
75 */
CanStartAdv(const string& addrStr)76 bool CanStartAdv(const string& addrStr)
77 {
78 lock_guard<mutex> lock(g_mapQueMutex);
79 HILOGI("addr: %{public}s", GetEncryptAddr(addrStr).c_str());
80 uint64_t currentMillis = GetBootMillis();
81 auto addrTime = g_advAddrMap.find(addrStr);
82 if (addrTime != g_advAddrMap.end()) {
83 if (currentMillis >= addrTime->second + ADV_ADDR_TIME_THRESHOLD) {
84 HILOGW("has the same adv addr in [15mins, 60mins]: %{public}s", GetEncryptAddr(addrStr).c_str());
85 return false;
86 } else {
87 return true;
88 }
89 }
90 if (g_advTimeQueue.size() >= MAX_ADV_ADDR_MAP_SIZE) {
91 g_advAddrMap.erase(g_advTimeQueue.front().first);
92 g_advTimeQueue.pop();
93 }
94 g_advTimeQueue.push(pair<string, uint64_t>(addrStr, currentMillis));
95 g_advAddrMap.insert(make_pair(addrStr, currentMillis));
96 return true;
97 }
98
99 } // namespace Bluetooth
100 } // namespace OHOS
101 #ifdef __cplusplus
102 }
103 #endif