1 /*
2 * Copyright (c) 2022 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 "dm_discovery_filter.h"
17
18 #include "dm_anonymous.h"
19 #include "dm_constants.h"
20 #include "dm_device_info.h"
21 #include "dm_log.h"
22 #include "nlohmann/json.hpp"
23
24 namespace OHOS {
25 namespace DistributedHardware {
26 const std::string FILTERS_KEY = "filters";
27 const std::string FILTER_OP_KEY = "filter_op";
28 const std::string FILTERS_TYPE_OR = "OR";
29 const std::string FILTERS_TYPE_AND = "AND";
30
31 enum DmDiscoveryDeviceFilter {
32 DM_INVALID_DEVICE = 0,
33 DM_VALID_DEVICE = 1,
34 DM_ALL_DEVICE = 2
35 };
36
ParseFilterJson(const std::string & str)37 int32_t DmDeviceFilterOption::ParseFilterJson(const std::string &str)
38 {
39 nlohmann::json jsonObject = nlohmann::json::parse(str, nullptr, false);
40 if (jsonObject.is_discarded()) {
41 LOGE("FilterOptions parse error.");
42 return ERR_DM_INPUT_PARA_INVALID;
43 }
44 if (!jsonObject.contains(FILTERS_KEY) || !jsonObject[FILTERS_KEY].is_array() || jsonObject[FILTERS_KEY].empty()) {
45 LOGE("Filters invalid.");
46 return ERR_DM_INPUT_PARA_INVALID;
47 }
48 if (jsonObject.contains(FILTER_OP_KEY) && !jsonObject[FILTER_OP_KEY].is_string()) {
49 LOGE("Filters_op invalid.");
50 return ERR_DM_INPUT_PARA_INVALID;
51 }
52 if (!jsonObject.contains(FILTER_OP_KEY)) {
53 filterOp_ = FILTERS_TYPE_OR; // filterOp optional, "OR" default
54 } else {
55 jsonObject[FILTER_OP_KEY].get_to(filterOp_);
56 }
57
58 for (const auto &object : jsonObject[FILTERS_KEY]) {
59 if (!object.contains("type") || !object["type"].is_string()) {
60 LOGE("Filters type invalid");
61 return ERR_DM_INPUT_PARA_INVALID;
62 }
63 if (!object.contains("value") || !object["value"].is_number_integer()) {
64 LOGE("Filters value invalid");
65 return ERR_DM_INPUT_PARA_INVALID;
66 }
67 DmDeviceFilters deviceFilters;
68 deviceFilters.type = object["type"];
69 deviceFilters.value = object["value"];
70 filters_.push_back(deviceFilters);
71 }
72 return DM_OK;
73 }
74
ParseFilterOptionJson(const std::string & str)75 void DmDeviceFilterOption::ParseFilterOptionJson(const std::string &str)
76 {
77 nlohmann::json object = nlohmann::json::parse(str, nullptr, false);
78 if (object.is_discarded()) {
79 LOGE("FilterOptions parse error.");
80 return;
81 }
82 filterOp_ = FILTERS_TYPE_AND;
83 DmDeviceFilters deviceFilters;
84 if (!object.contains("credible") || !object["credible"].is_number_integer()) {
85 LOGE("Filters credible type invalid");
86 } else {
87 deviceFilters.type = "credible";
88 deviceFilters.value = object["credible"];
89 filters_.push_back(deviceFilters);
90 }
91
92 if (!object.contains("range") || !object["range"].is_number_integer()) {
93 LOGE("Filters range type invalid");
94 } else {
95 deviceFilters.type = "range";
96 deviceFilters.value = object["range"];
97 filters_.push_back(deviceFilters);
98 }
99
100 if (!object.contains("isTrusted") || !object["isTrusted"].is_number_integer()) {
101 LOGE("Filters isTrusted type invalid");
102 } else {
103 deviceFilters.type = "isTrusted";
104 deviceFilters.value = object["isTrusted"];
105 filters_.push_back(deviceFilters);
106 }
107
108 if (!object.contains("authForm") || !object["authForm"].is_number_integer()) {
109 LOGE("Filters authForm type invalid");
110 } else {
111 deviceFilters.type = "authForm";
112 deviceFilters.value = object["authForm"];
113 filters_.push_back(deviceFilters);
114 }
115
116 if (!object.contains("deviceType") || !object["deviceType"].is_number_integer()) {
117 LOGE("Filters deviceType type invalid");
118 } else {
119 deviceFilters.type = "deviceType";
120 deviceFilters.value = object["deviceType"];
121 filters_.push_back(deviceFilters);
122 }
123 }
124
TransformToFilter(const std::string & filterOptions)125 int32_t DmDeviceFilterOption::TransformToFilter(const std::string &filterOptions)
126 {
127 if (filterOptions.empty()) {
128 LOGI("DmDeviceFilterOption::filterOptions empty");
129 filterOp_ = FILTERS_TYPE_OR;
130 DmDeviceFilters deviceFilters;
131 deviceFilters.type = "credible";
132 deviceFilters.value = DM_INVALID_DEVICE;
133 filters_.push_back(deviceFilters);
134 return DM_OK;
135 }
136 return ParseFilterJson(filterOptions);
137 }
138
TransformFilterOption(const std::string & filterOptions)139 void DmDeviceFilterOption::TransformFilterOption(const std::string &filterOptions)
140 {
141 if (filterOptions.empty()) {
142 LOGI("DmDeviceFilterOption::filterOptions empty");
143 filterOp_ = FILTERS_TYPE_OR;
144 DmDeviceFilters deviceFilters;
145 deviceFilters.type = "credible";
146 deviceFilters.value = DM_INVALID_DEVICE;
147 filters_.push_back(deviceFilters);
148 return;
149 }
150 ParseFilterOptionJson(filterOptions);
151 }
152
FilterByDeviceState(int32_t value,bool isActive)153 bool DmDiscoveryFilter::FilterByDeviceState(int32_t value, bool isActive)
154 {
155 if (value == DM_INVALID_DEVICE) {
156 return !isActive;
157 }
158 if (value == DM_VALID_DEVICE) {
159 return isActive;
160 }
161 return (value == DM_ALL_DEVICE);
162 }
163
FilterByRange(int32_t value,int32_t range)164 bool DmDiscoveryFilter::FilterByRange(int32_t value, int32_t range)
165 {
166 return ((range > 0) && (range <= value));
167 }
168
FilterByAuthForm(int32_t value,int32_t authForm)169 bool DmDiscoveryFilter::FilterByAuthForm(int32_t value, int32_t authForm)
170 {
171 return (value == authForm);
172 }
173
FilterByDeviceType(int32_t value,int32_t deviceType)174 bool DmDiscoveryFilter::FilterByDeviceType(int32_t value, int32_t deviceType)
175 {
176 return (value == deviceType);
177 }
178
FilterByType(const DmDeviceFilters & filters,const DmDeviceFilterPara & filterPara)179 bool DmDiscoveryFilter::FilterByType(const DmDeviceFilters &filters, const DmDeviceFilterPara &filterPara)
180 {
181 LOGI("DmDiscoveryFilter::FilterByType: type: %{public}s, value: %{public}d", filters.type.c_str(), filters.value);
182 if (filters.type == "credible") {
183 return FilterByDeviceState(filters.value, filterPara.isOnline);
184 }
185 if (filters.type == "range") {
186 return FilterByRange(filters.value, filterPara.range);
187 }
188 if (filters.type == "isTrusted") {
189 return FilterByDeviceState(filters.value, filterPara.isTrusted);
190 }
191 if (filters.type == "authForm") {
192 return FilterByAuthForm(filters.value, filterPara.authForm);
193 }
194 if (filters.type == "deviceType") {
195 return FilterByDeviceType(filters.value, filterPara.deviceType);
196 }
197 return false;
198 }
199
FilterOr(const std::vector<DmDeviceFilters> & filters,const DmDeviceFilterPara & filterPara)200 bool DmDiscoveryFilter::FilterOr(const std::vector<DmDeviceFilters> &filters, const DmDeviceFilterPara &filterPara)
201 {
202 for (auto &iter : filters) {
203 if (FilterByType(iter, filterPara) == true) {
204 return true;
205 }
206 }
207 return false;
208 }
209
FilterAnd(const std::vector<DmDeviceFilters> & filters,const DmDeviceFilterPara & filterPara)210 bool DmDiscoveryFilter::FilterAnd(const std::vector<DmDeviceFilters> &filters, const DmDeviceFilterPara &filterPara)
211 {
212 for (auto &iter : filters) {
213 if (FilterByType(iter, filterPara) == false) {
214 return false;
215 }
216 }
217 return true;
218 }
219
IsValidDevice(const std::string & filterOp,const std::vector<DmDeviceFilters> & filters,const DmDeviceFilterPara & filterPara)220 bool DmDiscoveryFilter::IsValidDevice(const std::string &filterOp, const std::vector<DmDeviceFilters> &filters,
221 const DmDeviceFilterPara &filterPara)
222 {
223 LOGI("DmDiscoveryFilter::IsValidDevice: filterOp: %{public}s, isOnline: %{public}d, range: %{public}d, isTrusted:"
224 "%{public}d, authForm: %{public}d, deviceType: %{public}d", filterOp.c_str(), filterPara.isOnline,
225 filterPara.range, filterPara.isTrusted, filterPara.authForm, filterPara.deviceType);
226 if (filterOp == FILTERS_TYPE_OR) {
227 return FilterOr(filters, filterPara);
228 }
229 if (filterOp == FILTERS_TYPE_AND) {
230 return FilterAnd(filters, filterPara);
231 }
232 return false;
233 }
234 } // namespace DistributedHardware
235 } // namespace OHOS