• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "route_head_handler_impl.h"
16 
17 #define LOG_TAG "RouteHeadHandler"
18 #include <chrono>
19 #include <cinttypes>
20 #include "auth_delegate.h"
21 #include "device_manager_adapter.h"
22 #include "kvstore_meta_manager.h"
23 #include "log_print.h"
24 #include "metadata/meta_data_manager.h"
25 #include "metadata/store_meta_data.h"
26 #include "securec.h"
27 #include "upgrade_manager.h"
28 #include "bootstrap.h"
29 #include "utils/anonymous.h"
30 #include "utils/endian_converter.h"
31 
32 namespace OHOS::DistributedData {
33 using namespace OHOS::DistributedKv;
34 using namespace std::chrono;
35 using DmAdapter = DistributedData::DeviceManagerAdapter;
36 constexpr const int ALIGN_WIDTH = 8;
Create(const ExtendInfo & info)37 std::shared_ptr<RouteHeadHandler> RouteHeadHandlerImpl::Create(const ExtendInfo &info)
38 {
39     auto handler = std::make_shared<RouteHeadHandlerImpl>(info);
40     if (handler == nullptr) {
41         ZLOGE("new instance failed");
42         return nullptr;
43     }
44     handler->Init();
45     return handler;
46 }
47 
RouteHeadHandlerImpl(const ExtendInfo & info)48 RouteHeadHandlerImpl::RouteHeadHandlerImpl(const ExtendInfo &info)
49     : userId_(info.userId), appId_(info.appId), storeId_(info.storeId), deviceId_(info.dstTarget), headSize_(0)
50 {
51     ZLOGD("init route handler, app:%{public}s, user:%{public}s, peer:%{public}s", appId_.c_str(), userId_.c_str(),
52         Anonymous::Change(deviceId_).c_str());
53 }
54 
Init()55 void RouteHeadHandlerImpl::Init()
56 {
57     ZLOGD("begin");
58     if (deviceId_.empty()) {
59         return;
60     }
61     SessionPoint localPoint { DmAdapter::GetInstance().GetLocalDevice().uuid,
62         static_cast<uint32_t>(atoi(userId_.c_str())), appId_, storeId_ };
63     session_ = SessionManager::GetInstance().GetSession(localPoint, deviceId_);
64     ZLOGD("valid session:appId:%{public}s, srcDevId:%{public}s, srcUser:%{public}u, trgDevId:%{public}s,",
65           session_.appId.c_str(), Anonymous::Change(session_.sourceDeviceId).c_str(),
66           session_.sourceUserId, Anonymous::Change(session_.targetDeviceId).c_str());
67 }
68 
GetHeadDataSize(uint32_t & headSize)69 DistributedDB::DBStatus RouteHeadHandlerImpl::GetHeadDataSize(uint32_t &headSize)
70 {
71     ZLOGD("begin");
72     headSize = 0;
73     if (appId_ == Bootstrap::GetInstance().GetProcessLabel()) {
74         ZLOGI("meta data permitted");
75         return DistributedDB::OK;
76     }
77     bool flag = false;
78     auto peerCap = UpgradeManager::GetInstance().GetCapability(session_.targetDeviceId, flag);
79     auto devInfo = DmAdapter::GetInstance().GetDeviceInfo(session_.targetDeviceId);
80     if (devInfo.osType != OH_OS_TYPE && devInfo.deviceType ==
81         static_cast<uint32_t>(DistributedHardware::DmDeviceType::DEVICE_TYPE_CAR)) {
82         ZLOGI("type car set version. devicdId:%{public}s", Anonymous::Change(session_.targetDeviceId).c_str());
83         flag = true;
84         peerCap.version = CapMetaData::CURRENT_VERSION;
85     }
86     if (!flag) {
87         ZLOGI("get peer cap failed");
88         return DistributedDB::DB_ERROR;
89     }
90     if (peerCap.version == CapMetaData::INVALID_VERSION) {
91         // older versions ignore pack extend head
92         ZLOGI("ignore older version device");
93         return DistributedDB::OK;
94     }
95     if (!session_.IsValid()) {
96         ZLOGI("no valid session to peer device");
97         return DistributedDB::DB_ERROR;
98     }
99     size_t expectSize = sizeof(RouteHead) + sizeof(SessionDevicePair) + sizeof(SessionUserPair)
100                         + session_.targetUserIds.size() * sizeof(int) + sizeof(SessionAppId) + session_.appId.size();
101 
102     // align message uint width
103     headSize = GET_ALIGNED_SIZE(expectSize, ALIGN_WIDTH);
104     auto time =
105         static_cast<uint64_t>(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count());
106     ZLOGI("packed size:%{public}u times %{public}" PRIu64 ".", headSize, time);
107     headSize_ = headSize;
108     return DistributedDB::OK;
109 }
110 
FillHeadData(uint8_t * data,uint32_t headSize,uint32_t totalLen)111 DistributedDB::DBStatus RouteHeadHandlerImpl::FillHeadData(uint8_t *data, uint32_t headSize, uint32_t totalLen)
112 {
113     ZLOGD("begin");
114     if (headSize != headSize_) {
115         ZLOGI("size not match");
116         return DistributedDB::DB_ERROR;
117     }
118     if (headSize_ == 0) {
119         ZLOGI("ignore older version device");
120         return DistributedDB::OK;
121     }
122     auto packRet = PackData(data, headSize);
123     ZLOGD("pack result:%{public}d", packRet);
124     return packRet ? DistributedDB::OK : DistributedDB::DB_ERROR;
125 }
126 
PackData(uint8_t * data,uint32_t totalLen)127 bool RouteHeadHandlerImpl::PackData(uint8_t *data, uint32_t totalLen)
128 {
129     if (headSize_ > totalLen) {
130         ZLOGE("the buffer size is not enough, headSize:%{public}d, tatalLen:%{public}d",
131             headSize_, totalLen);
132         return false;
133     }
134 
135     auto isOk = PackDataHead(data, headSize_);
136     if (isOk) {
137         return PackDataBody(data + sizeof(RouteHead), headSize_ - sizeof(RouteHead));
138     }
139     return false;
140 }
141 
PackDataHead(uint8_t * data,uint32_t totalLen)142 bool RouteHeadHandlerImpl::PackDataHead(uint8_t *data, uint32_t totalLen)
143 {
144     uint8_t *ptr = data;
145     if (headSize_ < sizeof(RouteHead)) {
146         return false;
147     }
148     RouteHead *head = reinterpret_cast<RouteHead *>(ptr);
149     head->magic = HostToNet(RouteHead::MAGIC_NUMBER);
150     head->version = HostToNet(RouteHead::VERSION);
151     head->checkSum = HostToNet(uint64_t(0));
152     head->dataLen = HostToNet(uint32_t(totalLen - sizeof(RouteHead)));
153     return true;
154 }
155 
PackDataBody(uint8_t * data,uint32_t totalLen)156 bool RouteHeadHandlerImpl::PackDataBody(uint8_t *data, uint32_t totalLen)
157 {
158     uint8_t *ptr = data;
159     SessionDevicePair *devicePair = reinterpret_cast<SessionDevicePair *>(ptr);
160     auto ret = strcpy_s(devicePair->sourceId, SessionDevicePair::MAX_DEVICE_ID, session_.sourceDeviceId.c_str());
161     if (ret != 0) {
162         ZLOGE("strcpy for source device id failed, ret is %{public}d", ret);
163         return false;
164     }
165     ret = strcpy_s(devicePair->targetId, SessionDevicePair::MAX_DEVICE_ID, session_.targetDeviceId.c_str());
166     if (ret != 0) {
167         ZLOGE("strcpy for target device id failed, ret is %{public}d", ret);
168         return false;
169     }
170     ptr += sizeof(SessionDevicePair);
171 
172     SessionUserPair *userPair = reinterpret_cast<SessionUserPair *>(ptr);
173     userPair->sourceUserId = HostToNet(session_.sourceUserId);
174     userPair->targetUserCount = session_.targetUserIds.size();
175     for (size_t i = 0; i < session_.targetUserIds.size(); ++i) {
176         *(userPair->targetUserIds + i) = HostToNet(session_.targetUserIds[i]);
177     }
178     ptr += (sizeof(SessionUserPair) + session_.targetUserIds.size() * sizeof(int));
179 
180     SessionAppId *appPair = reinterpret_cast<SessionAppId *>(ptr);
181     ptr += sizeof(SessionAppId);
182 
183     uint8_t *end = data + totalLen;
184     uint32_t appIdSize = session_.appId.size();
185     ret = memcpy_s(appPair->appId, end - ptr, session_.appId.data(), appIdSize);
186     if (ret != 0) {
187         ZLOGE("strcpy for app id failed, error:%{public}d", errno);
188         return false;
189     }
190     appPair->len = HostToNet(appIdSize);
191     return true;
192 }
193 
ParseHeadData(const uint8_t * data,uint32_t len,uint32_t & headSize,std::vector<std::string> & users)194 bool RouteHeadHandlerImpl::ParseHeadData(
195     const uint8_t *data, uint32_t len, uint32_t &headSize, std::vector<std::string> &users)
196 {
197     auto ret = UnPackData(data, len, headSize);
198     if (!ret) {
199         headSize = 0;
200         return false;
201     }
202     auto time =
203         static_cast<uint64_t>(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count());
204     ZLOGI("unpacked size:%{public}u times %{public}" PRIu64 ".", headSize, time);
205     // flip the local and peer ends
206     SessionPoint local { .deviceId = session_.targetDeviceId, .appId = session_.appId };
207     SessionPoint peer { .deviceId = session_.sourceDeviceId, .userId = session_.sourceUserId, .appId = session_.appId };
208     ZLOGD("valid session:appId:%{public}s, srcDevId:%{public}s, srcUser:%{public}u, trgDevId:%{public}s,",
209           session_.appId.c_str(), Anonymous::Change(session_.sourceDeviceId).c_str(),
210           session_.sourceUserId, Anonymous::Change(session_.targetDeviceId).c_str());
211     for (const auto &item : session_.targetUserIds) {
212         local.userId = item;
213         if (SessionManager::GetInstance().CheckSession(local, peer)) {
214             users.emplace_back(std::to_string(item));
215         }
216     }
217     return true;
218 }
219 
UnPackData(const uint8_t * data,uint32_t totalLen,uint32_t & unpackedSize)220 bool RouteHeadHandlerImpl::UnPackData(const uint8_t *data, uint32_t totalLen, uint32_t &unpackedSize)
221 {
222     if (data == nullptr || totalLen < sizeof(RouteHead)) {
223         ZLOGE("invalid input data, totalLen:%{public}d", totalLen);
224         return false;
225     }
226     unpackedSize = 0;
227     RouteHead head = { 0 };
228     bool result = UnPackDataHead(data, totalLen, head);
229     if (result && head.version == RouteHead::VERSION) {
230         auto isOk = UnPackDataBody(data + sizeof(RouteHead), totalLen - sizeof(RouteHead));
231         if (isOk) {
232             unpackedSize = sizeof(RouteHead) + head.dataLen;
233         }
234         return isOk;
235     }
236     return false;
237 }
238 
UnPackDataHead(const uint8_t * data,uint32_t totalLen,RouteHead & routeHead)239 bool RouteHeadHandlerImpl::UnPackDataHead(const uint8_t *data, uint32_t totalLen, RouteHead &routeHead)
240 {
241     if (totalLen < sizeof(RouteHead)) {
242         ZLOGE("invalid route head len:%{public}d", totalLen);
243         return false;
244     }
245     const RouteHead *head = reinterpret_cast<const RouteHead *>(data);
246     routeHead.magic = NetToHost(head->magic);
247     routeHead.version = NetToHost(head->version);
248     routeHead.checkSum = NetToHost(head->checkSum);
249     routeHead.dataLen = NetToHost(head->dataLen);
250     if (routeHead.magic != RouteHead::MAGIC_NUMBER) {
251         ZLOGD("not route head data");
252         return false;
253     }
254     if (totalLen - sizeof(RouteHead) < routeHead.dataLen) {
255         ZLOGE("invalid route data len:%{public}d, totalLen:%{public}d.", routeHead.dataLen, totalLen);
256         return false;
257     }
258     return true;
259 }
260 
UnPackDataBody(const uint8_t * data,uint32_t totalLen)261 bool RouteHeadHandlerImpl::UnPackDataBody(const uint8_t *data, uint32_t totalLen)
262 {
263     const uint8_t *ptr = data;
264     uint32_t leftSize = totalLen;
265 
266     if (leftSize < sizeof(SessionDevicePair)) {
267         ZLOGE("failed to parse device pair, leftSize : %{public}d", leftSize);
268         return false;
269     }
270     const SessionDevicePair *devicePair = reinterpret_cast<const SessionDevicePair *>(ptr);
271     session_.sourceDeviceId =
272         std::string(devicePair->sourceId, strnlen(devicePair->sourceId, SessionDevicePair::MAX_DEVICE_ID));
273     session_.targetDeviceId =
274         std::string(devicePair->targetId, strnlen(devicePair->targetId, SessionDevicePair::MAX_DEVICE_ID));
275     ptr += sizeof(SessionDevicePair);
276     leftSize -= sizeof(SessionDevicePair);
277 
278     if (leftSize < sizeof(SessionUserPair)) {
279         ZLOGE("failed to parse user pair, leftSize : %{public}d", leftSize);
280         return false;
281     }
282     const SessionUserPair *userPair = reinterpret_cast<const SessionUserPair *>(ptr);
283     session_.sourceUserId = NetToHost(userPair->sourceUserId);
284 
285     auto userPairSize = sizeof(SessionUserPair) + userPair->targetUserCount * sizeof(uint32_t);
286     if (leftSize < userPairSize) {
287         ZLOGE("failed to parse user pair, target user, leftSize : %{public}d", leftSize);
288         return false;
289     }
290     for (int i = 0; i < userPair->targetUserCount; ++i) {
291         session_.targetUserIds.push_back(NetToHost(*(userPair->targetUserIds + i)));
292     }
293     ptr += userPairSize;
294     leftSize -= userPairSize;
295 
296     if (leftSize < sizeof(SessionAppId)) {
297         ZLOGE("failed to parse app id, leftSize : %{public}d", leftSize);
298         return false;
299     }
300     const SessionAppId *appId = reinterpret_cast<const SessionAppId *>(ptr);
301     auto appIdLen = NetToHost(appId->len);
302     if (leftSize - sizeof(SessionAppId) < appIdLen) {
303         ZLOGE("failed to parse app id, appIdLen:%{public}d, leftSize:%{public}d.", appIdLen, leftSize);
304         return false;
305     }
306     session_.appId.append(appId->appId, appIdLen);
307     return true;
308 }
309 } // namespace OHOS::DistributedData