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