• 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 #define LOG_TAG "RdbServiceImpl"
16 #include "rdb_service_impl.h"
17 #include "accesstoken_kit.h"
18 #include "account/account_delegate.h"
19 #include "checker/checker_manager.h"
20 #include "communicator/communication_provider.h"
21 #include "crypto_manager.h"
22 #include "ipc_skeleton.h"
23 #include "log_print.h"
24 #include "metadata/meta_data_manager.h"
25 #include "metadata/store_meta_data.h"
26 #include "permission/permission_validator.h"
27 #include "types_export.h"
28 #include "utils/anonymous.h"
29 using OHOS::DistributedKv::AccountDelegate;
30 using OHOS::AppDistributedKv::CommunicationProvider;
31 using OHOS::DistributedData::CheckerManager;
32 using OHOS::DistributedData::MetaDataManager;
33 using OHOS::DistributedData::StoreMetaData;
34 using OHOS::DistributedData::Anonymous;
35 using namespace OHOS::DistributedData;
36 using DistributedDB::RelationalStoreManager;
37 
38 constexpr uint32_t ITERATE_TIMES = 10000;
39 namespace OHOS::DistributedRdb {
40 __attribute__((used)) RdbServiceImpl::Factory RdbServiceImpl::factory_;
Factory()41 RdbServiceImpl::Factory::Factory()
42 {
43     FeatureSystem::GetInstance().RegisterCreator("relational_store",
44         []() { return std::make_shared<RdbServiceImpl>(); });
45 }
46 
~Factory()47 RdbServiceImpl::Factory::~Factory()
48 {
49 }
50 
DeathRecipientImpl(const DeathCallback & callback)51 RdbServiceImpl::DeathRecipientImpl::DeathRecipientImpl(const DeathCallback& callback)
52     : callback_(callback)
53 {
54     ZLOGI("construct");
55 }
56 
~DeathRecipientImpl()57 RdbServiceImpl::DeathRecipientImpl::~DeathRecipientImpl()
58 {
59     ZLOGI("destroy");
60 }
61 
OnRemoteDied(const wptr<IRemoteObject> & object)62 void RdbServiceImpl::DeathRecipientImpl::OnRemoteDied(const wptr<IRemoteObject> &object)
63 {
64     ZLOGI("enter");
65     if (callback_) {
66         callback_();
67     }
68 }
69 
RdbServiceImpl()70 RdbServiceImpl::RdbServiceImpl()
71     : timer_("SyncerTimer", -1), autoLaunchObserver_(this)
72 {
73     ZLOGI("construct");
74     timer_.Setup();
75     DistributedDB::RelationalStoreManager::SetAutoLaunchRequestCallback(
76         [this](const std::string& identifier, DistributedDB::AutoLaunchParam &param) {
77             return ResolveAutoLaunch(identifier, param);
78         });
79 }
80 
ResolveAutoLaunch(const std::string & identifier,DistributedDB::AutoLaunchParam & param)81 int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam &param)
82 {
83     std::string identifierHex = TransferStringToHex(identifier);
84     ZLOGI("%{public}.6s", identifierHex.c_str());
85     std::vector<StoreMetaData> entries;
86     auto localId = CommunicationProvider::GetInstance().GetLocalDevice().uuid;
87     if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ localId }), entries)) {
88         ZLOGE("get meta failed");
89         return false;
90     }
91     ZLOGI("size=%{public}d", static_cast<int32_t>(entries.size()));
92     for (const auto& entry : entries) {
93         if (entry.storeType != RDB_DEVICE_COLLABORATION) {
94             continue;
95         }
96 
97         auto aIdentifier = DistributedDB::RelationalStoreManager::GetRelationalStoreIdentifier(
98             entry.user, entry.appId, entry.storeId);
99         ZLOGI("%{public}s %{public}s %{public}s", entry.user.c_str(), entry.appId.c_str(), entry.storeId.c_str());
100         if (aIdentifier != identifier) {
101             continue;
102         }
103         ZLOGI("find identifier %{public}s", entry.storeId.c_str());
104         param.userId = entry.user;
105         param.appId = entry.appId;
106         param.storeId = entry.storeId;
107         param.path = entry.dataDir;
108         param.option.storeObserver = &autoLaunchObserver_;
109         param.option.isEncryptedDb = entry.isEncrypt;
110         if (entry.isEncrypt) {
111             param.option.iterateTimes = ITERATE_TIMES;
112             param.option.cipher = DistributedDB::CipherType::AES_256_GCM;
113             RdbSyncer::GetPassword(entry, param.option.passwd);
114         }
115         return true;
116     }
117 
118     ZLOGE("not find identifier");
119     return false;
120 }
121 
OnClientDied(pid_t pid)122 void RdbServiceImpl::OnClientDied(pid_t pid)
123 {
124     ZLOGI("client dead pid=%{public}d", pid);
125     syncers_.ComputeIfPresent(pid, [this](const auto& key, StoreSyncersType& syncers) {
126         syncerNum_ -= static_cast<int32_t>(syncers.size());
127         for (const auto& [name, syncer] : syncers) {
128             timer_.Unregister(syncer->GetTimerId());
129         }
130         return false;
131     });
132     notifiers_.Erase(pid);
133     identifiers_.EraseIf([pid](const auto& key, pid_t& value) {
134         return pid == value;
135     });
136 }
137 
CheckAccess(const RdbSyncerParam & param)138 bool RdbServiceImpl::CheckAccess(const RdbSyncerParam &param)
139 {
140     CheckerManager::StoreInfo storeInfo;
141     storeInfo.uid = IPCSkeleton::GetCallingUid();
142     storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
143     storeInfo.bundleName = param.bundleName_;
144     storeInfo.storeId = RdbSyncer::RemoveSuffix(param.storeName_);
145     auto instanceId = RdbSyncer::GetInstIndex(storeInfo.tokenId, storeInfo.bundleName);
146     if (instanceId != 0) {
147         return false;
148     }
149     return !CheckerManager::GetInstance().GetAppId(storeInfo).empty();
150 }
151 
ObtainDistributedTableName(const std::string & device,const std::string & table)152 std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table)
153 {
154     ZLOGI("device=%{public}s table=%{public}s", Anonymous::Change(device).c_str(), table.c_str());
155     auto uuid = AppDistributedKv::CommunicationProvider::GetInstance().GetUuidByNodeId(device);
156     if (uuid.empty()) {
157         ZLOGE("get uuid failed");
158         return "";
159     }
160     return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table);
161 }
162 
InitNotifier(const RdbSyncerParam & param,const sptr<IRemoteObject> notifier)163 int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam& param, const sptr<IRemoteObject> notifier)
164 {
165     if (!CheckAccess(param)) {
166         ZLOGE("permission error");
167         return RDB_ERROR;
168     }
169 
170     pid_t pid = IPCSkeleton::GetCallingPid();
171     auto recipient = new(std::nothrow) DeathRecipientImpl([this, pid] {
172         OnClientDied(pid);
173     });
174     if (recipient == nullptr) {
175         ZLOGE("malloc recipient failed");
176         return RDB_ERROR;
177     }
178 
179     if (!notifier->AddDeathRecipient(recipient)) {
180         ZLOGE("link to death failed");
181         return RDB_ERROR;
182     }
183     notifiers_.Insert(pid, iface_cast<RdbNotifierProxy>(notifier));
184     ZLOGI("success pid=%{public}d", pid);
185 
186     return RDB_OK;
187 }
188 
OnDataChange(pid_t pid,const DistributedDB::StoreChangedData & data)189 void RdbServiceImpl::OnDataChange(pid_t pid, const DistributedDB::StoreChangedData &data)
190 {
191     DistributedDB::StoreProperty property;
192     data.GetStoreProperty(property);
193     ZLOGI("%{public}d %{public}s", pid, property.storeId.c_str());
194     if (pid == 0) {
195         auto identifier = RelationalStoreManager::GetRelationalStoreIdentifier(property.userId, property.appId,
196                                                                                property.storeId);
197         auto pair = identifiers_.Find(TransferStringToHex(identifier));
198         if (!pair.first) {
199             ZLOGI("client doesn't subscribe");
200             return;
201         }
202         pid = pair.second;
203         ZLOGI("fixed pid=%{public}d", pid);
204     }
205     notifiers_.ComputeIfPresent(pid, [&data, &property] (const auto& key, const sptr<RdbNotifierProxy>& value) {
206         std::string device = data.GetDataChangeDevice();
207         auto networkId = CommunicationProvider::GetInstance().ToNodeId(device);
208         value->OnChange(property.storeId, { networkId });
209         return true;
210     });
211 }
212 
SyncerTimeout(std::shared_ptr<RdbSyncer> syncer)213 void RdbServiceImpl::SyncerTimeout(std::shared_ptr<RdbSyncer> syncer)
214 {
215     if (syncer == nullptr) {
216         return;
217     }
218     ZLOGI("%{public}s", syncer->GetStoreId().c_str());
219     syncers_.ComputeIfPresent(syncer->GetPid(), [this, &syncer](const auto& key, StoreSyncersType& syncers) {
220         syncers.erase(syncer->GetStoreId());
221         syncerNum_--;
222         return true;
223     });
224 }
225 
GetRdbSyncer(const RdbSyncerParam & param)226 std::shared_ptr<RdbSyncer> RdbServiceImpl::GetRdbSyncer(const RdbSyncerParam &param)
227 {
228     pid_t pid = IPCSkeleton::GetCallingPid();
229     pid_t uid = IPCSkeleton::GetCallingUid();
230     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
231     std::shared_ptr<RdbSyncer> syncer;
232     syncers_.Compute(pid, [this, &param, pid, uid, tokenId, &syncer] (const auto& key, StoreSyncersType& syncers) {
233         auto storeId = RdbSyncer::RemoveSuffix(param.storeName_);
234         auto it = syncers.find(storeId);
235         if (it != syncers.end()) {
236             syncer = it->second;
237             if (!param.isEncrypt_ || param.password_.empty()) {
238                 timer_.Unregister(syncer->GetTimerId());
239                 uint32_t timerId = timer_.Register([this, syncer]() { SyncerTimeout(syncer); }, SYNCER_TIMEOUT, true);
240                 syncer->SetTimerId(timerId);
241                 return true;
242             }
243             syncers.erase(storeId);
244         }
245         if (syncers.size() >= MAX_SYNCER_PER_PROCESS) {
246             ZLOGE("%{public}d exceed MAX_PROCESS_SYNCER_NUM", pid);
247             return !syncers.empty();
248         }
249         if (syncerNum_ >= MAX_SYNCER_NUM) {
250             ZLOGE("no available syncer");
251             return !syncers.empty();
252         }
253         auto syncer_ = std::make_shared<RdbSyncer>(param, new (std::nothrow) RdbStoreObserverImpl(this, pid));
254         if (syncer_->Init(pid, uid, tokenId) != 0) {
255             return !syncers.empty();
256         }
257         syncers[storeId] = syncer_;
258         syncer = syncer_;
259         syncerNum_++;
260         uint32_t timerId = timer_.Register([this, syncer]() { SyncerTimeout(syncer); }, SYNCER_TIMEOUT, true);
261         syncer->SetTimerId(timerId);
262         return !syncers.empty();
263     });
264 
265     if (syncer != nullptr) {
266         identifiers_.Insert(syncer->GetIdentifier(), pid);
267     } else {
268         ZLOGE("syncer is nullptr");
269     }
270     return syncer;
271 }
272 
SetDistributedTables(const RdbSyncerParam & param,const std::vector<std::string> & tables)273 int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam &param, const std::vector<std::string> &tables)
274 {
275     ZLOGI("enter");
276     if (!CheckAccess(param)) {
277         ZLOGE("permission error");
278         return RDB_ERROR;
279     }
280     auto syncer = GetRdbSyncer(param);
281     if (syncer == nullptr) {
282         return RDB_ERROR;
283     }
284     return syncer->SetDistributedTables(tables);
285 }
286 
DoSync(const RdbSyncerParam & param,const SyncOption & option,const RdbPredicates & predicates,SyncResult & result)287 int32_t RdbServiceImpl::DoSync(const RdbSyncerParam &param, const SyncOption &option,
288                                const RdbPredicates &predicates, SyncResult &result)
289 {
290     if (!CheckAccess(param)) {
291         ZLOGE("permission error");
292         return RDB_ERROR;
293     }
294     auto syncer = GetRdbSyncer(param);
295     if (syncer == nullptr) {
296         return RDB_ERROR;
297     }
298     return syncer->DoSync(option, predicates, result);
299 }
300 
OnAsyncComplete(pid_t pid,uint32_t seqNum,const SyncResult & result)301 void RdbServiceImpl::OnAsyncComplete(pid_t pid, uint32_t seqNum, const SyncResult &result)
302 {
303     ZLOGI("pid=%{public}d seqnum=%{public}u", pid, seqNum);
304     notifiers_.ComputeIfPresent(pid, [seqNum, &result] (const auto& key, const sptr<RdbNotifierProxy>& value) {
305         value->OnComplete(seqNum, result);
306         return true;
307     });
308 }
309 
DoAsync(const RdbSyncerParam & param,uint32_t seqNum,const SyncOption & option,const RdbPredicates & predicates)310 int32_t RdbServiceImpl::DoAsync(const RdbSyncerParam &param, uint32_t seqNum, const SyncOption &option,
311                                 const RdbPredicates &predicates)
312 {
313     if (!CheckAccess(param)) {
314         ZLOGE("permission error");
315         return RDB_ERROR;
316     }
317     pid_t pid = IPCSkeleton::GetCallingPid();
318     ZLOGI("seq num=%{public}u", seqNum);
319     auto syncer = GetRdbSyncer(param);
320     if (syncer == nullptr) {
321         return RDB_ERROR;
322     }
323     return syncer->DoAsync(option, predicates,
324                            [this, pid, seqNum] (const SyncResult& result) {
325                                OnAsyncComplete(pid, seqNum, result);
326                            });
327 }
328 
TransferStringToHex(const std::string & origStr)329 std::string RdbServiceImpl::TransferStringToHex(const std::string &origStr)
330 {
331     if (origStr.empty()) {
332         return "";
333     }
334     const char *hex = "0123456789abcdef";
335     std::string tmp;
336     for (auto item : origStr) {
337         auto currentByte = static_cast<uint8_t>(item);
338         tmp.push_back(hex[currentByte >> 4]); // high 4 bit to one hex.
339         tmp.push_back(hex[currentByte & 0x0F]); // low 4 bit to one hex.
340     }
341     return tmp;
342 }
343 
GenIdentifier(const RdbSyncerParam & param)344 std::string RdbServiceImpl::GenIdentifier(const RdbSyncerParam &param)
345 {
346     pid_t uid = IPCSkeleton::GetCallingUid();
347     uint32_t token = IPCSkeleton::GetCallingTokenID();
348     auto storeId = RdbSyncer::RemoveSuffix(param.storeName_);
349     CheckerManager::StoreInfo storeInfo{ uid, token, param.bundleName_, storeId };
350     std::string userId = AccountDelegate::GetInstance()->GetDeviceAccountIdByUID(uid);
351     std::string appId = CheckerManager::GetInstance().GetAppId(storeInfo);
352     std::string identifier = RelationalStoreManager::GetRelationalStoreIdentifier(userId, appId, storeId);
353     return TransferStringToHex(identifier);
354 }
355 
DoSubscribe(const RdbSyncerParam & param)356 int32_t RdbServiceImpl::DoSubscribe(const RdbSyncerParam& param)
357 {
358     pid_t pid = IPCSkeleton::GetCallingPid();
359     auto identifier = GenIdentifier(param);
360     ZLOGI("%{public}s %{public}.6s %{public}d", param.storeName_.c_str(), identifier.c_str(), pid);
361     identifiers_.Insert(identifier, pid);
362     return RDB_OK;
363 }
364 
DoUnSubscribe(const RdbSyncerParam & param)365 int32_t RdbServiceImpl::DoUnSubscribe(const RdbSyncerParam& param)
366 {
367     auto identifier = GenIdentifier(param);
368     ZLOGI("%{public}s %{public}.6s", param.storeName_.c_str(), identifier.c_str());
369     identifiers_.Erase(identifier);
370     return RDB_OK;
371 }
372 
RemoteQuery(const RdbSyncerParam & param,const std::string & device,const std::string & sql,const std::vector<std::string> & selectionArgs,sptr<IRemoteObject> & resultSet)373 int32_t RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql,
374                                     const std::vector<std::string>& selectionArgs, sptr<IRemoteObject>& resultSet)
375 {
376     if (!CheckAccess(param)) {
377         ZLOGE("permission error");
378         return RDB_ERROR;
379     }
380     auto syncer = GetRdbSyncer(param);
381     if (syncer == nullptr) {
382         ZLOGE("syncer is null");
383         return RDB_ERROR;
384     }
385     return syncer->RemoteQuery(device, sql, selectionArgs, resultSet);
386 }
387 
CreateRDBTable(const RdbSyncerParam & param,const std::string & writePermission,const std::string & readPermission)388 int32_t RdbServiceImpl::CreateRDBTable(
389     const RdbSyncerParam &param, const std::string &writePermission, const std::string &readPermission)
390 {
391     if (!CheckAccess(param)) {
392         ZLOGE("permission error");
393         return RDB_ERROR;
394     }
395 
396     pid_t pid = IPCSkeleton::GetCallingPid();
397     auto syncer = new (std::nothrow)RdbSyncer(param, new (std::nothrow) RdbStoreObserverImpl(this, pid));
398     if (syncer == nullptr) {
399         ZLOGE("new syncer error");
400         return RDB_ERROR;
401     }
402     auto uid = IPCSkeleton::GetCallingUid();
403     auto tokenId = IPCSkeleton::GetCallingTokenID();
404     if (syncer->Init(pid, uid, tokenId, writePermission, readPermission) != RDB_OK) {
405         ZLOGE("Init error");
406         delete syncer;
407         return RDB_ERROR;
408     }
409     delete syncer;
410     return RDB_OK;
411 }
412 
DestroyRDBTable(const RdbSyncerParam & param)413 int32_t RdbServiceImpl::DestroyRDBTable(const RdbSyncerParam &param)
414 {
415     if (!CheckAccess(param)) {
416         ZLOGE("permission error");
417         return RDB_ERROR;
418     }
419     pid_t pid = IPCSkeleton::GetCallingPid();
420     auto syncer = new (std::nothrow)RdbSyncer(param, new (std::nothrow) RdbStoreObserverImpl(this, pid));
421     if (syncer == nullptr) {
422         ZLOGE("new syncer error");
423         return RDB_ERROR;
424     }
425 
426     StoreMetaData meta;
427     if (syncer->DestroyMetaData(meta) != RDB_OK) {
428         ZLOGE("Init error");
429         delete syncer;
430         return RDB_ERROR;
431     }
432     delete syncer;
433     return RDB_OK;
434 }
435 } // namespace OHOS::DistributedRdb
436