1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
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 "bluetooth_ble_filter_matcher.h"
17 
18 namespace OHOS {
19 namespace Bluetooth {
20 using namespace OHOS::bluetooth;
MatchesScanFilters(const std::vector<bluetooth::BleScanFilterImpl> & bleScanFilters,const BluetoothBleScanResult & result)21 MatchResult BluetoothBleFilterMatcher::MatchesScanFilters(
22     const std::vector<bluetooth::BleScanFilterImpl> &bleScanFilters,
23     const BluetoothBleScanResult &result)
24 {
25     // no filters equals all result pass
26     if (bleScanFilters.empty()) {
27         return MatchResult::MATCH;
28     }
29 
30     for (const auto &filter : bleScanFilters) {
31         if (MatchesScanFilter(filter, result) == MatchResult::MATCH) {
32             return MatchResult::MATCH;
33         }
34     }
35     return MatchResult::MISMATCH;
36 }
37 
MatchesScanFilter(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)38 MatchResult BluetoothBleFilterMatcher::MatchesScanFilter(
39     const bluetooth::BleScanFilterImpl &filter,
40     const BluetoothBleScanResult &result)
41 {
42     if (MatchesAddress(filter, result) == MatchResult::MISMATCH) {
43         return MatchResult::MISMATCH;
44     }
45 
46     if (MatchesName(filter, result) == MatchResult::MISMATCH) {
47         return MatchResult::MISMATCH;
48     }
49 
50     if (MatchesServiceUuids(filter, result) == MatchResult::MISMATCH) {
51         return MatchResult::MISMATCH;
52     }
53 
54     if (MatchesManufacturerDatas(filter, result) == MatchResult::MISMATCH) {
55         return MatchResult::MISMATCH;
56     }
57 
58     if (MatchesServiceDatas(filter, result) == MatchResult::MISMATCH) {
59         return MatchResult::MISMATCH;
60     }
61 
62     return MatchResult::MATCH;
63 }
64 
MatchesAddress(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)65 MatchResult BluetoothBleFilterMatcher::MatchesAddress(const bluetooth::BleScanFilterImpl &filter,
66     const BluetoothBleScanResult &result)
67 {
68     std::string filterAddress = filter.GetDeviceId();
69     // no fiilter equals all result pass
70     if (filterAddress.empty()) {
71         return MatchResult::MATCH;
72     }
73 
74     std::string resultAdderss = result.GetPeripheralDevice().GetAddress();
75     if (resultAdderss.empty()) {
76         return MatchResult::MISMATCH;
77     }
78 
79     return filterAddress == resultAdderss ? MatchResult::MATCH : MatchResult::MISMATCH;
80 }
81 
MatchesName(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)82 MatchResult BluetoothBleFilterMatcher::MatchesName(const bluetooth::BleScanFilterImpl &filter,
83     const BluetoothBleScanResult &result)
84 {
85     std::string filterName = filter.GetName();
86     // no fiilter equals all result pass
87     if (filterName.empty()) {
88         return MatchResult::MATCH;
89     }
90 
91     std::string resultName = result.GetName();
92     if (resultName.empty()) {
93         return MatchResult::MISMATCH;
94     }
95 
96     return filterName == resultName ? MatchResult::MATCH : MatchResult::MISMATCH;
97 }
98 
MatchesServiceUuids(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)99 MatchResult BluetoothBleFilterMatcher::MatchesServiceUuids(const bluetooth::BleScanFilterImpl &filter,
100     const BluetoothBleScanResult &result)
101 {
102     // no fiilter equals all result pass
103     if (!filter.HasServiceUuid()) {
104         return MatchResult::MATCH;
105     }
106     bluetooth::Uuid filterUuid = filter.GetServiceUuid();
107 
108     std::vector<bluetooth::Uuid> resultUuids = result.GetServiceUuids();
109     // if filter needs but result is empty means fail
110     if (resultUuids.empty()) {
111         return MatchResult::MISMATCH;
112     }
113 
114     for (auto &uuid : resultUuids) {
115         // mask means filter = result
116         if (!filter.HasServiceUuidMask()) {
117             if (filterUuid.operator == (uuid)) {
118                 return MatchResult::MATCH;
119             }
120         }
121 
122         // mask means filter&&mask = result&&mask
123         if (filter.HasServiceUuidMask()) {
124             bluetooth::Uuid uuidMask = filter.GetServiceUuidMask();
125             if (MatchesUuidWithMask(filterUuid, uuid, uuidMask)) {
126             return MatchResult::MATCH;
127             }
128         }
129     }
130     return MatchResult::MISMATCH;
131 }
132 
MatchesManufacturerDatas(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)133 MatchResult BluetoothBleFilterMatcher::MatchesManufacturerDatas(const bluetooth::BleScanFilterImpl &filter,
134     const BluetoothBleScanResult &result)
135 {
136     uint16_t filterManufacturerId = filter.GetManufacturerId();
137     std::vector<uint8_t> filterData = filter.GetManufactureData();
138     std::vector<uint8_t> fiilterDataMask = filter.GetManufactureDataMask();
139     // no fiilter equals all result pass
140     if (filterData.size() == 0) {
141         return MatchResult::MATCH;
142     }
143     // if filter needs but result is empty means fail
144     if (result.GetManufacturerData().empty()) {
145         return MatchResult::MISMATCH;
146     }
147 
148     for (auto &resultManufacturerData : result.GetManufacturerData()) {
149         // if ManufacturerId same then check data
150         if (filterManufacturerId == resultManufacturerData.first) {
151             bool result = MatchesData(filterData, resultManufacturerData.second, fiilterDataMask);
152             return result ? MatchResult::MATCH : MatchResult::MISMATCH;
153         }
154     }
155     return MatchResult::MISMATCH;
156 }
157 
MatchesServiceDatas(const bluetooth::BleScanFilterImpl & filter,const BluetoothBleScanResult & result)158 MatchResult BluetoothBleFilterMatcher::MatchesServiceDatas(const bluetooth::BleScanFilterImpl &filter,
159     const BluetoothBleScanResult &result)
160 {
161     std::vector<uint8_t> filterData = filter.GetServiceData();
162     std::vector<uint8_t> dataMask = filter.GetServiceDataMask();
163     // no Filter equals all result pass
164     if (filterData.size() == 0) {
165         return MatchResult::MATCH;
166     }
167     // if filter needs but result is empty means fail
168     if (result.GetServiceData().empty()) {
169         return MatchResult::MISMATCH;
170     }
171     for (auto &serviceData : result.GetServiceData()) {
172         std::string resultData = ParseServiceDataUUidToString(serviceData.first, serviceData.second);
173         if (MatchesData(filterData, resultData, dataMask)) {
174             return MatchResult::MATCH;
175         }
176     }
177     return MatchResult::MISMATCH;
178 }
179 
MatchesUuidWithMask(bluetooth::Uuid filterUuid,bluetooth::Uuid uuid,bluetooth::Uuid uuidMask)180 bool BluetoothBleFilterMatcher::MatchesUuidWithMask(bluetooth::Uuid filterUuid,
181     bluetooth::Uuid uuid, bluetooth::Uuid uuidMask)
182 {
183     HILOGI("enter");
184     uint8_t uuid128[bluetooth::Uuid::UUID128_BYTES_TYPE];
185     uint8_t uuidMask128[bluetooth::Uuid::UUID128_BYTES_TYPE];
186     uint8_t resultUuid128[bluetooth::Uuid::UUID128_BYTES_TYPE];
187     if (!filterUuid.ConvertToBytesLE(uuid128)) {
188         HILOGE("Convert filter uuid faild.");
189         return false;
190     }
191     if (!uuidMask.ConvertToBytesLE(uuidMask128)) {
192         HILOGE("Convert uuid mask faild.");
193         return false;
194     }
195     if (!uuid.ConvertToBytesLE(resultUuid128)) {
196         HILOGE("Convert result uuid faild.");
197         return false;
198     }
199     size_t maskLength = sizeof(uuidMask128);
200     if (maskLength <= 0) {
201         return false;
202     }
203 
204     for (size_t i = 0; i < maskLength; i++) {
205         if ((uuid128[i] & uuidMask128[i]) != (resultUuid128[i] & uuidMask128[i])) {
206             return false;
207         }
208     }
209 
210     return true;
211 }
212 
ParseServiceDataUUidToString(bluetooth::Uuid uuid,std::string data)213 std::string BluetoothBleFilterMatcher::ParseServiceDataUUidToString(bluetooth::Uuid uuid, std::string data)
214 {
215     std::string tmpServcieData;
216     int uuidType = uuid.GetUuidType();
217     switch (uuidType) {
218         case bluetooth::Uuid::UUID16_BYTES_TYPE: {
219             uint16_t uuid16 = uuid.ConvertTo16Bits();
220             tmpServcieData = std::string(reinterpret_cast<char *>(&uuid16), BLE_UUID_LEN_16);
221             break;
222         }
223         case bluetooth::Uuid::UUID32_BYTES_TYPE: {
224             uint32_t uuid32 = uuid.ConvertTo32Bits();
225             tmpServcieData = std::string(reinterpret_cast<char *>(&uuid32), BLE_UUID_LEN_32);
226             break;
227         }
228         case bluetooth::Uuid::UUID128_BYTES_TYPE: {
229             uint8_t uuid128[bluetooth::Uuid::UUID128_BYTES_TYPE];
230             if (!uuid.ConvertToBytesLE(uuid128)) {
231                 HILOGE("Convert filter uuid faild.");
232             }
233             tmpServcieData = std::string(reinterpret_cast<char *>(&uuid128), BLE_UUID_LEN_128);
234             break;
235         }
236         default:
237             break;
238     }
239     return tmpServcieData + data;
240 }
241 
MatchesData(std::vector<uint8_t> fData,std::string rData,std::vector<uint8_t> dataMask)242 bool BluetoothBleFilterMatcher::MatchesData(std::vector<uint8_t> fData,
243     std::string rData, std::vector<uint8_t> dataMask)
244 {
245     if (rData.empty()) {
246         return false;
247     }
248 
249     size_t length = fData.size();
250     std::vector<uint8_t> vec(rData.begin(), rData.end());
251     if (vec.size() < length) {
252         return false;
253     }
254 
255     if (dataMask.empty() || dataMask.size() != length) {
256         for (size_t i = 0; i < length; i++) {
257             if (fData[i] != vec[i]) {
258                 return false;
259             }
260         }
261         return true;
262     }
263     for (size_t i = 0; i < length; i++) {
264         if ((fData[i] & dataMask[i]) != (vec[i] & dataMask[i])) {
265             return false;
266         }
267     }
268     return true;
269 }
270 }  // namespace Bluetooth
271 }  // namespace OHOS