From d3d52ceb3a2b7a8e792d82737afa349fbcbc5d7a Mon Sep 17 00:00:00 2001 From: yangguangzhao Date: Thu, 21 Apr 2022 11:24:17 +0800 Subject: [PATCH] RPC version control and access token supportted Signed-off-by: yangguangzhao --- bundle.json | 2 +- interfaces/innerkits/ipc_core/BUILD.gn | 2 + interfaces/innerkits/libdbinder/BUILD.gn | 5 +- .../libdbinder/include/dbinder_service.h | 8 +- ipc/native/c/rpc/include/rpc_feature_set.h | 50 ++++++ ipc/native/c/rpc/src/rpc_feature_set.c | 69 ++++++++ ipc/native/src/core/include/comm_auth_info.h | 6 +- .../src/core/include/dbinder_callback_stub.h | 9 +- .../src/core/include/dbinder_session_object.h | 4 + .../src/core/include/ipc_process_skeleton.h | 6 +- ipc/native/src/core/source/comm_auth_info.cpp | 10 +- .../src/core/source/dbinder_callback_stub.cpp | 13 +- .../core/source/dbinder_session_object.cpp | 10 ++ .../src/core/source/ipc_object_proxy.cpp | 23 ++- .../src/core/source/ipc_object_stub.cpp | 26 ++- .../src/core/source/ipc_process_skeleton.cpp | 11 +- ipc/native/src/core/source/message_parcel.cpp | 9 +- .../src/mock/include/dbinder_base_invoker.h | 25 ++- .../mock/include/dbinder_databus_invoker.h | 2 + .../mock/source/dbinder_databus_invoker.cpp | 48 +++++- ipc/test/BUILD.gn | 5 +- .../dbinder_service/src/dbinder_service.cpp | 56 ++++--- .../src/dbinder_service_stub.cpp | 3 +- services/dbinder/test/BUILD.gn | 7 +- services/dbinder/test/moduletest/BUILD.gn | 80 +++++++++ .../test/moduletest/include/rpc_test.h | 80 +++++++++ .../test/moduletest/src/rpc_client_test.cpp | 88 ++++++++++ .../test/moduletest/src/rpc_server_test.cpp | 63 ++++++++ .../dbinder/test/moduletest/src/rpc_test.cpp | 153 ++++++++++++++++++ 29 files changed, 812 insertions(+), 61 deletions(-) create mode 100644 ipc/native/c/rpc/include/rpc_feature_set.h create mode 100644 ipc/native/c/rpc/src/rpc_feature_set.c create mode 100644 services/dbinder/test/moduletest/BUILD.gn create mode 100644 services/dbinder/test/moduletest/include/rpc_test.h create mode 100644 services/dbinder/test/moduletest/src/rpc_client_test.cpp create mode 100644 services/dbinder/test/moduletest/src/rpc_server_test.cpp create mode 100644 services/dbinder/test/moduletest/src/rpc_test.cpp diff --git a/bundle.json b/bundle.json index 316d18e..c01d179 100644 --- a/bundle.json +++ b/bundle.json @@ -12,7 +12,7 @@ "component": { "name": "ipc", "subsystem": "communication", - "adapted_system_type": [ + "adapted_system_type": [ "standard" ], "features": [], diff --git a/interfaces/innerkits/ipc_core/BUILD.gn b/interfaces/innerkits/ipc_core/BUILD.gn index ccc94e9..6d450be 100644 --- a/interfaces/innerkits/ipc_core/BUILD.gn +++ b/interfaces/innerkits/ipc_core/BUILD.gn @@ -23,11 +23,13 @@ config("libipc_core_private_config") { ohos_shared_library("ipc_core") { include_dirs = [ "$IPC_CORE_ROOT/c/adapter/access_token/include", + "$IPC_CORE_ROOT/c/rpc/include", "$SUBSYSTEM_DIR/utils/include", "//base/hiviewdfx/hitrace/interfaces/native/innerkits/include", ] sources = [ "$IPC_CORE_ROOT/c/adapter/access_token/src/access_token_adapter.c", + "$IPC_CORE_ROOT/c/rpc/src/rpc_feature_set.c", "$IPC_CORE_ROOT/src/core/source/buffer_object.cpp", "$IPC_CORE_ROOT/src/core/source/comm_auth_info.cpp", "$IPC_CORE_ROOT/src/core/source/databus_session_callback.cpp", diff --git a/interfaces/innerkits/libdbinder/BUILD.gn b/interfaces/innerkits/libdbinder/BUILD.gn index 24bec75..ae06fb0 100644 --- a/interfaces/innerkits/libdbinder/BUILD.gn +++ b/interfaces/innerkits/libdbinder/BUILD.gn @@ -39,7 +39,10 @@ config("libdbinder_private_config") { } ohos_shared_library("libdbinder") { - include_dirs = [ "$SUBSYSTEM_DIR/utils/include" ] + include_dirs = [ + "$SUBSYSTEM_DIR/ipc/native/c/rpc/include", + "$SUBSYSTEM_DIR/utils/include", + ] sources = [ "$DBINDER_ROOT/dbinder_service/src/dbinder_death_recipient.cpp", "$DBINDER_ROOT/dbinder_service/src/dbinder_sa_death_recipient.cpp", diff --git a/interfaces/innerkits/libdbinder/include/dbinder_service.h b/interfaces/innerkits/libdbinder/include/dbinder_service.h index 40c5a61..22f504b 100644 --- a/interfaces/innerkits/libdbinder/include/dbinder_service.h +++ b/interfaces/innerkits/libdbinder/include/dbinder_service.h @@ -54,8 +54,7 @@ struct DHandleEntryTxRx { struct DHandleEntryHead head; uint32_t transType; uint32_t dBinderCode; - uint16_t fromPort; - uint16_t toPort; + uint32_t rpcFeatureSet; uint64_t stubIndex; uint32_t seqNumber; binder_uintptr_t binderObject; @@ -70,8 +69,7 @@ struct DHandleEntryTxRx { struct SessionInfo { uint32_t seqNumber; uint32_t type; - uint16_t toPort; - uint16_t fromPort; + uint32_t rpcFeatureSet; uint64_t stubIndex; uint32_t socketFd; std::string serviceName; @@ -165,6 +163,8 @@ private: bool RegisterRemoteProxyInner(std::u16string serviceName, binder_uintptr_t binder); bool CheckSystemAbilityId(int32_t systemAbilityId); bool IsSameSession(std::shared_ptr oldSession, std::shared_ptr nowSession); + bool HandleInvokeListenThread(IPCObjectProxy *proxy, uint64_t stubIndex, std::string serverSessionName, + struct DHandleEntryTxRx *replyMessage); private: DISALLOW_COPY_AND_MOVE(DBinderService); diff --git a/ipc/native/c/rpc/include/rpc_feature_set.h b/ipc/native/c/rpc/include/rpc_feature_set.h new file mode 100644 index 0000000..c2bdb8d --- /dev/null +++ b/ipc/native/c/rpc/include/rpc_feature_set.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_RPC_FEATURE_SET_H +#define OHOS_RPC_FEATURE_SET_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t magicNum; + uint32_t tag; + uint32_t tokenId; +} AccessTokenData; + +typedef struct { + uint32_t featureSet; + uint32_t tokenId; +} FeatureSetData; + +uint32_t GetFeatureMagicNumber(void); +uint32_t GetFeatureATTag(void); +uint32_t GetLocalRpcFeature(void); +uint32_t GetRpcFeatureAck(void); +bool IsATEnable(uint32_t featureSet); +bool IsFeatureAck(uint32_t featureSet); +size_t GetATSize(uint32_t featureSet); +uint32_t GetTokenIdSize(void); + +#ifdef __cplusplus +} +#endif +#endif // OHOS_RPC_FEATURE_SET_H \ No newline at end of file diff --git a/ipc/native/c/rpc/src/rpc_feature_set.c b/ipc/native/c/rpc/src/rpc_feature_set.c new file mode 100644 index 0000000..c46c73f --- /dev/null +++ b/ipc/native/c/rpc/src/rpc_feature_set.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rpc_feature_set.h" + +#define RPC_FEATURE_LAST (43) +#define RPC_ACCESS_TOKEN_FLAG 0x1 + +static const uint32_t RPC_FEATURE_MAGIC_NUM = ('R' << 24) | ('F' << 16) | ('S' << 8) | RPC_FEATURE_LAST; +static const uint32_t RPC_ACCESS_TOKEN = 0; +static const uint32_t RpcFeatureFlag = 0x1; +static const uint32_t TokenIdSize = 4; +static const uint32_t RpcFeatureAck = 0x80000000; + +uint32_t GetFeatureMagicNumber(void) +{ + return RPC_FEATURE_MAGIC_NUM; +} + +uint32_t GetFeatureATTag(void) +{ + return RPC_ACCESS_TOKEN; +} + +uint32_t GetLocalRpcFeature(void) +{ + return RpcFeatureFlag; +} + +uint32_t GetRpcFeatureAck(void) +{ + return RpcFeatureAck; +} + +bool IsATEnable(uint32_t featureSet) +{ + return (featureSet & RPC_ACCESS_TOKEN_FLAG) > 0; +} + +bool IsFeatureAck(uint32_t featureSet) +{ + return (featureSet & RpcFeatureAck) > 0; +} + +size_t GetATSize(uint32_t featureSet) +{ + size_t atSize = 0; + if (IsATEnable(featureSet) == true) { + atSize += sizeof(AccessTokenData); + } + return atSize; +} + +uint32_t GetTokenIdSize(void) +{ + return TokenIdSize; +} \ No newline at end of file diff --git a/ipc/native/src/core/include/comm_auth_info.h b/ipc/native/src/core/include/comm_auth_info.h index 0125d42..37e4031 100644 --- a/ipc/native/src/core/include/comm_auth_info.h +++ b/ipc/native/src/core/include/comm_auth_info.h @@ -18,22 +18,26 @@ #include "iremote_object.h" #include "ipc_object_stub.h" +#include "rpc_feature_set.h" namespace OHOS { class CommAuthInfo { public: - CommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId); + CommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId, + std::shared_ptr featureSet); virtual ~CommAuthInfo(); const IRemoteObject *GetStubObject() const; int GetRemotePid() const; int GetRemoteUid() const; std::string GetRemoteDeviceId() const; + std::shared_ptr GetFeatureSet() const; private: IRemoteObject *stub_; int remotePid_; int remoteUid_; std::string deviceId_; + std::shared_ptr featureSet_; }; } // namespace OHOS #endif // OHOS_IPC_COMMAUTHINFO_H \ No newline at end of file diff --git a/ipc/native/src/core/include/dbinder_callback_stub.h b/ipc/native/src/core/include/dbinder_callback_stub.h index c8c7df2..26bd6c0 100644 --- a/ipc/native/src/core/include/dbinder_callback_stub.h +++ b/ipc/native/src/core/include/dbinder_callback_stub.h @@ -19,12 +19,14 @@ #include #include "ipc_object_stub.h" +#include "rpc_feature_set.h" namespace OHOS { class DBinderCallbackStub : public IPCObjectStub { public: explicit DBinderCallbackStub(const std::string &serviceName, const std::string &peerDeviceID, - const std::string &localDeviceID, uint64_t stubIndex, uint32_t handle); + const std::string &localDeviceID, uint64_t stubIndex, uint32_t handle, + std::shared_ptr feature); ~DBinderCallbackStub(); int32_t ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; @@ -32,6 +34,10 @@ public: const std::string &GetServiceName(); const std::string &GetDeviceID(); uint64_t GetStubIndex() const; + std::shared_ptr GetFeatureSet() const; + +private: + uint32_t ConstructAuthData(MessageParcel &authData, uint32_t featureSet); private: const std::string serviceName_; @@ -39,6 +45,7 @@ private: const std::string localDeviceID_; uint64_t stubIndex_; uint32_t handle_; + std::shared_ptr rpcFeatureSet_; }; } // namespace OHOS #endif // OHOS_IPC_DBINDER_CALLBACK_STUB_H \ No newline at end of file diff --git a/ipc/native/src/core/include/dbinder_session_object.h b/ipc/native/src/core/include/dbinder_session_object.h index 9c43ae7..5d5d64a 100644 --- a/ipc/native/src/core/include/dbinder_session_object.h +++ b/ipc/native/src/core/include/dbinder_session_object.h @@ -21,6 +21,7 @@ #include "nocopyable.h" #include "buffer_object.h" +#include "rpc_feature_set.h" #include "Session.h" #include "ISessionService.h" @@ -51,10 +52,12 @@ public: void SetBusSession(std::shared_ptr session); void SetServiceName(const std::string &serviceName); void SetDeviceId(const std::string &serverDeviceId); + void SetFeatureSet(std::shared_ptr rpcFeatureSet); std::shared_ptr GetSessionBuff(); std::shared_ptr GetBusSession() const; std::string GetServiceName() const; std::string GetDeviceId() const; + std::shared_ptr GetFeatureSet() const; uint32_t GetSessionHandle() const; void CloseDatabusSession(); @@ -66,6 +69,7 @@ private: std::shared_ptr buff_; std::string serviceName_; std::string serverDeviceId_; + std::shared_ptr rpcFeatureSet_; }; } // namespace OHOS #endif // OHOS_IPC_DBINDER_SESSION_OBJECT_H \ No newline at end of file diff --git a/ipc/native/src/core/include/ipc_process_skeleton.h b/ipc/native/src/core/include/ipc_process_skeleton.h index 0d9206c..eef3f27 100644 --- a/ipc/native/src/core/include/ipc_process_skeleton.h +++ b/ipc/native/src/core/include/ipc_process_skeleton.h @@ -33,6 +33,7 @@ #include "comm_auth_info.h" #include "dbinder_callback_stub.h" #include "dbinder_session_object.h" +#include "rpc_feature_set.h" #include "ISessionService.h" #include "Session.h" #include "stub_refcount_object.h" @@ -169,10 +170,11 @@ public: bool DecStubRefTimes(IRemoteObject *stub); bool DetachStubRefTimes(IRemoteObject *stub); - bool AttachCommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId); + bool AttachCommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId, + std::shared_ptr featureSet); void DetachCommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId); void DetachCommAuthInfoByStub(IRemoteObject *stub); - bool QueryIsAuth(int pid, int uid, const std::string &deviceId); + std::shared_ptr QueryIsAuth(int pid, int uid, const std::string &deviceId); bool AddDataThreadToIdle(const std::thread::id &threadId); bool DeleteDataThreadFromIdle(const std::thread::id &threadId); std::thread::id GetIdleDataThread(); diff --git a/ipc/native/src/core/source/comm_auth_info.cpp b/ipc/native/src/core/source/comm_auth_info.cpp index 41eae67..1adb9d9 100644 --- a/ipc/native/src/core/source/comm_auth_info.cpp +++ b/ipc/native/src/core/source/comm_auth_info.cpp @@ -16,8 +16,9 @@ #include "comm_auth_info.h" namespace OHOS { -CommAuthInfo::CommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId) - : stub_(stub), remotePid_(pid), remoteUid_(uid), deviceId_(deviceId) +CommAuthInfo::CommAuthInfo(IRemoteObject *stub, int pid, int uid, + const std::string &deviceId, std::shared_ptr featureSet) + : stub_(stub), remotePid_(pid), remoteUid_(uid), deviceId_(deviceId), featureSet_(featureSet) {} CommAuthInfo::~CommAuthInfo() @@ -40,4 +41,9 @@ std::string CommAuthInfo::GetRemoteDeviceId() const { return deviceId_; } + +std::shared_ptr CommAuthInfo::GetFeatureSet() const +{ + return featureSet_; +} } // namespace OHOS diff --git a/ipc/native/src/core/source/dbinder_callback_stub.cpp b/ipc/native/src/core/source/dbinder_callback_stub.cpp index 25d4803..6decffb 100644 --- a/ipc/native/src/core/source/dbinder_callback_stub.cpp +++ b/ipc/native/src/core/source/dbinder_callback_stub.cpp @@ -38,13 +38,14 @@ static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC, (void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args) DBinderCallbackStub::DBinderCallbackStub(const std::string &service, const std::string &device, - const std::string &localDevice, uint64_t stubIndex, uint32_t handle) + const std::string &localDevice, uint64_t stubIndex, uint32_t handle, std::shared_ptr feature) : IPCObjectStub(Str8ToStr16("DBinderCallback" + device + service)), serviceName_(service), deviceID_(device), localDeviceID_(localDevice), stubIndex_(stubIndex), - handle_(handle) + handle_(handle), + rpcFeatureSet_(feature) { DBINDER_LOGI("serviceName:%{public}s, deviceId:%{public}s, handle:%{public}u, stubIndex_:%{public}" PRIu64 "", serviceName_.c_str(), deviceID_.c_str(), handle_, stubIndex_); @@ -70,6 +71,11 @@ uint64_t DBinderCallbackStub::GetStubIndex() const return stubIndex_; } +std::shared_ptr DBinderCallbackStub::GetFeatureSet() const +{ + return rpcFeatureSet_; +} + int32_t DBinderCallbackStub::ProcessProto(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { @@ -93,8 +99,9 @@ int32_t DBinderCallbackStub::ProcessProto(uint32_t code, MessageParcel &data, Me MessageParcel authData, authReply; MessageOption authOption; + uint32_t featureSet = rpcFeatureSet_->featureSet; if (!authData.WriteUint32(pid) || !authData.WriteUint32(uid) || !authData.WriteString(localDeviceID_) || - !authData.WriteUint64(stubIndex_)) { + !authData.WriteUint32(featureSet) || !authData.WriteUint64(stubIndex_)) { DBINDER_LOGE("write to MessageParcel fail"); return ERR_INVALID_DATA; } diff --git a/ipc/native/src/core/source/dbinder_session_object.cpp b/ipc/native/src/core/source/dbinder_session_object.cpp index 7c7fe88..c08de8c 100644 --- a/ipc/native/src/core/source/dbinder_session_object.cpp +++ b/ipc/native/src/core/source/dbinder_session_object.cpp @@ -87,11 +87,21 @@ void DBinderSessionObject::SetDeviceId(const std::string &serverDeviceId) serverDeviceId_ = serverDeviceId; } +void DBinderSessionObject::SetFeatureSet(std::shared_ptr rpcFeatureSet) +{ + rpcFeatureSet_ = rpcFeatureSet; +} + std::string DBinderSessionObject::GetDeviceId() const { return serverDeviceId_; } +std::shared_ptr DBinderSessionObject::GetFeatureSet() const +{ + return rpcFeatureSet_; +} + uint32_t DBinderSessionObject::GetFlatSessionLen() { return sizeof(struct FlatDBinderSession); diff --git a/ipc/native/src/core/source/ipc_object_proxy.cpp b/ipc/native/src/core/source/ipc_object_proxy.cpp index 9799641..905b5eb 100644 --- a/ipc/native/src/core/source/ipc_object_proxy.cpp +++ b/ipc/native/src/core/source/ipc_object_proxy.cpp @@ -24,7 +24,9 @@ #include "securec.h" #ifndef CONFIG_IPC_SINGLE +#include "access_token_adapter.h" #include "dbinder_databus_invoker.h" +#include "rpc_feature_set.h" #endif namespace OHOS { @@ -605,6 +607,19 @@ bool IPCObjectProxy::UpdateDatabusClientSession(int handle, MessageParcel &reply std::string peerID = reply.ReadString(); std::string localID = reply.ReadString(); std::string localBusName = reply.ReadString(); + uint32_t rpcFeatureSet = reply.ReadUint32(); + uint32_t tokenId = 0; + if (IsATEnable(rpcFeatureSet) == true) { + tokenId = RpcGetSelfTokenID(); + } + std::shared_ptr featureSet = nullptr; + featureSet.reset(reinterpret_cast(::operator new(sizeof(FeatureSetData)))); + if (featureSet == nullptr) { + ZLOGE(LABEL, "%s: featureSet null", __func__); + return false; + } + featureSet->featureSet = rpcFeatureSet; + featureSet->tokenId = tokenId; IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); if (current == nullptr) { @@ -620,6 +635,7 @@ bool IPCObjectProxy::UpdateDatabusClientSession(int handle, MessageParcel &reply return false; } } + connectSession->SetFeatureSet(featureSet); if (!current->AttachHandleToIndex((uint32_t)handle, stubIndex)) { ZLOGE(LABEL, "add stub index err stubIndex = %" PRIu64 ", handle = %d", stubIndex, handle); @@ -632,12 +648,7 @@ bool IPCObjectProxy::UpdateDatabusClientSession(int handle, MessageParcel &reply } bool result = invoker->UpdateClientSession(handle, connectSession); - if (!result) { - ZLOGE(LABEL, "update server session object fail!"); - return false; - } - - return true; + return result; } void IPCObjectProxy::ReleaseDatabusProto() diff --git a/ipc/native/src/core/source/ipc_object_stub.cpp b/ipc/native/src/core/source/ipc_object_stub.cpp index 7138189..9c4812e 100644 --- a/ipc/native/src/core/source/ipc_object_stub.cpp +++ b/ipc/native/src/core/source/ipc_object_stub.cpp @@ -25,6 +25,7 @@ #ifndef CONFIG_IPC_SINGLE #include "dbinder_databus_invoker.h" #include "dbinder_error_code.h" +#include "rpc_feature_set.h" #include "ISessionService.h" #endif @@ -352,6 +353,16 @@ int32_t IPCObjectStub::InvokerDataBusThread(MessageParcel &data, MessageParcel & uint32_t remoteUid = data.ReadUint32(); std::string remoteDeviceId = data.ReadString(); std::string sessionName = data.ReadString(); + uint32_t featureSet = data.ReadUint32(); + uint32_t tokenId = 0; + + std::shared_ptr feature = std::make_shared(); + if (feature == nullptr) { + ZLOGE(LABEL, "%s: feature null", __func__); + return IPC_STUB_INVALID_DATA_ERR; + } + feature->featureSet = featureSet; + feature->tokenId = tokenId; if (IsDeviceIdIllegal(deviceId) || IsDeviceIdIllegal(remoteDeviceId) || sessionName.empty()) { ZLOGE(LABEL, "%s: device ID is invalid or session name nil", __func__); return IPC_STUB_INVALID_DATA_ERR; @@ -379,7 +390,7 @@ int32_t IPCObjectStub::InvokerDataBusThread(MessageParcel &data, MessageParcel & if (!current->AttachAppInfoToStubIndex(remotePid, remoteUid, remoteDeviceId, stubIndex)) { ZLOGE(LABEL, "fail to attach appinfo to stubIndex, maybe attach already"); } - if (!current->AttachCommAuthInfo(this, (int32_t)remotePid, (int32_t)remoteUid, remoteDeviceId)) { + if (!current->AttachCommAuthInfo(this, (int32_t)remotePid, (int32_t)remoteUid, remoteDeviceId, feature)) { ZLOGE(LABEL, "fail to attach comm auth info"); } @@ -453,6 +464,17 @@ int32_t IPCObjectStub::AddAuthInfo(MessageParcel &data, MessageParcel &reply, ui uint32_t remotePid = data.ReadUint32(); uint32_t remoteUid = data.ReadUint32(); std::string remoteDeviceId = data.ReadString(); + uint32_t remoteFeature = data.ReadUint32(); + uint32_t tokenId = 0; + + std::shared_ptr feature = nullptr; + feature.reset(reinterpret_cast(::operator new(sizeof(FeatureSetData)))); + if (feature == nullptr) { + ZLOGE(LABEL, "%s: feature null", __func__); + return IPC_STUB_INVALID_DATA_ERR; + } + feature->featureSet = remoteFeature; + feature->tokenId = tokenId; if (IsDeviceIdIllegal(remoteDeviceId)) { ZLOGE(LABEL, "%s: remote deviceId is null", __func__); return IPC_STUB_INVALID_DATA_ERR; @@ -464,7 +486,7 @@ int32_t IPCObjectStub::AddAuthInfo(MessageParcel &data, MessageParcel &reply, ui return IPC_STUB_CURRENT_NULL_ERR; } - if (!current->AttachCommAuthInfo(this, (int32_t)remotePid, (int32_t)remoteUid, remoteDeviceId)) { + if (!current->AttachCommAuthInfo(this, (int32_t)remotePid, (int32_t)remoteUid, remoteDeviceId, feature)) { ZLOGE(LABEL, "fail to attach comm auth info fail"); return IPC_STUB_INVALID_DATA_ERR; } diff --git a/ipc/native/src/core/source/ipc_process_skeleton.cpp b/ipc/native/src/core/source/ipc_process_skeleton.cpp index 1d5143f..9b48891 100644 --- a/ipc/native/src/core/source/ipc_process_skeleton.cpp +++ b/ipc/native/src/core/source/ipc_process_skeleton.cpp @@ -1200,7 +1200,8 @@ bool IPCProcessSkeleton::IsSameRemoteObject(int pid, int uid, const std::string } } -bool IPCProcessSkeleton::AttachCommAuthInfo(IRemoteObject *stub, int pid, int uid, const std::string &deviceId) +bool IPCProcessSkeleton::AttachCommAuthInfo(IRemoteObject *stub, int pid, int uid, + const std::string &deviceId, std::shared_ptr featureSet) { auto check = [&stub, &pid, &uid, &deviceId, this](const std::shared_ptr &auth) { return IsSameRemoteObject(stub, pid, uid, deviceId, auth); @@ -1213,7 +1214,7 @@ bool IPCProcessSkeleton::AttachCommAuthInfo(IRemoteObject *stub, int pid, int ui return true; } - std::shared_ptr authObject = std::make_shared(stub, pid, uid, deviceId); + std::shared_ptr authObject = std::make_shared(stub, pid, uid, deviceId, featureSet); commAuth_.push_front(authObject); return true; } @@ -1228,7 +1229,7 @@ void IPCProcessSkeleton::DetachCommAuthInfo(IRemoteObject *stub, int pid, int ui commAuth_.remove_if(check); } -bool IPCProcessSkeleton::QueryIsAuth(int pid, int uid, const std::string &deviceId) +std::shared_ptr IPCProcessSkeleton::QueryIsAuth(int pid, int uid, const std::string &deviceId) { auto check = [&pid, &uid, &deviceId, this](const std::shared_ptr &auth) { return IsSameRemoteObject(pid, uid, deviceId, auth); @@ -1237,10 +1238,10 @@ bool IPCProcessSkeleton::QueryIsAuth(int pid, int uid, const std::string &device std::shared_lock lockGuard(commAuthMutex_); auto it = std::find_if(commAuth_.begin(), commAuth_.end(), check); if (it != commAuth_.end()) { - return true; + return (*it)->GetFeatureSet(); } DBINDER_LOGE("Query Comm Auth Fail"); - return false; + return nullptr; } void IPCProcessSkeleton::DetachCommAuthInfoByStub(IRemoteObject *stub) diff --git a/ipc/native/src/core/source/message_parcel.cpp b/ipc/native/src/core/source/message_parcel.cpp index 4c6205a..9081851 100644 --- a/ipc/native/src/core/source/message_parcel.cpp +++ b/ipc/native/src/core/source/message_parcel.cpp @@ -22,6 +22,7 @@ #ifndef CONFIG_IPC_SINGLE #include "dbinder_callback_stub.h" #include "dbinder_session_object.h" +#include "rpc_feature_set.h" #endif #include "ipc_debug.h" #include "ipc_file_descriptor.h" @@ -108,10 +109,16 @@ bool MessageParcel::WriteDBinderProxy(const sptr &object, uint32_ std::string peerName = sessionOfPeer->GetServiceName(); std::string peerId = sessionOfPeer->GetDeviceId(); std::string localId = current->GetLocalDeviceID(); + std::shared_ptr feature = sessionOfPeer->GetFeatureSet(); + if (feature == nullptr) { + DBINDER_LOGE("feature is nullptr"); + return false; + } + sptr fakeStub = current->QueryDBinderCallbackStub(object); if (fakeStub == nullptr) { // note that cannot use this proxy's descriptor - fakeStub = new DBinderCallbackStub(peerName, peerId, localId, stubIndex, handle); + fakeStub = new DBinderCallbackStub(peerName, peerId, localId, stubIndex, handle, feature); if (!current->AttachDBinderCallbackStub(object, fakeStub)) { DBINDER_LOGE("save callback of fake stub failed"); return false; diff --git a/ipc/native/src/mock/include/dbinder_base_invoker.h b/ipc/native/src/mock/include/dbinder_base_invoker.h index 17dd595..910d566 100644 --- a/ipc/native/src/mock/include/dbinder_base_invoker.h +++ b/ipc/native/src/mock/include/dbinder_base_invoker.h @@ -100,8 +100,10 @@ public: virtual void SetCallerUid(pid_t uid) = 0; virtual void SetStatus(uint32_t status) = 0; virtual void SetCallerDeviceID(const std::string &deviceId) = 0; + virtual void SetCallerTokenID(const uint32_t tokenId) = 0; virtual int CheckAndSetCallerInfo(uint32_t listenFd, uint64_t stubIndex) = 0; virtual int OnSendRawData(std::shared_ptr session, const void *data, size_t size) = 0; + virtual bool SetTokenId(const dbinder_transaction_data *tr, uint32_t listenFd) = 0; bool CheckTransactionData(const dbinder_transaction_data *tr) const; private: @@ -447,6 +449,14 @@ std::shared_ptr DBinderBaseInvoker::ProcessNormalDa uint32_t sendSize = ((data.GetDataSize() > 0) ? data.GetDataSize() : sizeof(binder_size_t)) + sizeof(struct dbinder_transaction_data) + data.GetOffsetsSize() * T::GetFlatSessionLen() + data.GetOffsetsSize() * sizeof(binder_size_t); + std::shared_ptr feature = sessionObject->GetFeatureSet(); + if (feature == nullptr) { + DBINDER_BASE_LOGE("process normal data feature is null"); + return nullptr; + } + if (IsATEnable(feature->featureSet) == true) { + sendSize += GetTokenIdSize(); + } std::shared_ptr transData = nullptr; transData.reset(reinterpret_cast(::operator new(sendSize))); @@ -464,6 +474,11 @@ std::shared_ptr DBinderBaseInvoker::ProcessNormalDa DBINDER_BASE_LOGE("move parcel to transData failed, handle = %{public}d", handle); return nullptr; } + if (IsATEnable(feature->featureSet) == true) { + uint32_t bufferUseSize = transData->buffer_size + transData->offsets_size; + uint32_t *tokenIdAddr = (uint32_t *)(transData->buffer + bufferUseSize); + *tokenIdAddr = feature->tokenId; + } return transData; } @@ -493,7 +508,7 @@ bool DBinderBaseInvoker::MoveTransData2Buffer(std::shared_ptr sessionObjec DBINDER_BASE_LOGE("sender's data is large than idle buffer"); return false; } - if (memcpy_s(sendBuffer + writeCursor, sendSize, transData.get(), sendSize)) { + if (memcpy_s(sendBuffer + writeCursor, sendSize, transData.get(), sendSize) != EOK) { sessionBuff->ReleaseSendBufferLock(); DBINDER_BASE_LOGE("fail to copy from tr to sendBuffer, parcelSize = %{public}u", sendSize); return false; @@ -841,10 +856,15 @@ template void DBinderBaseInvoker::ProcessTransaction(dbinder_transa const auto oldUid = static_cast(GetCallerUid()); const std::string oldDeviceId = GetCallerDeviceID(); uint32_t oldStatus = GetStatus(); + const uint32_t oldTokenId = GetCallerTokenID(); if (CheckAndSetCallerInfo(listenFd, tr->cookie) != ERR_NONE) { DBINDER_BASE_LOGE("set user info error, maybe cookie is NOT belong to current caller"); return; } + if (SetTokenId(tr, listenFd) != true) { + DBINDER_BASE_LOGE("set tokenid failed"); + return; + } SetStatus(IRemoteInvoker::ACTIVE_INVOKER); const uint32_t flags = tr->flags; @@ -889,6 +909,7 @@ template void DBinderBaseInvoker::ProcessTransaction(dbinder_transa SetCallerUid(oldUid); SetCallerDeviceID(oldDeviceId); SetStatus(oldStatus); + SetCallerTokenID(oldTokenId); } template void DBinderBaseInvoker::ProcessReply(dbinder_transaction_data *tr, uint32_t listenFd) @@ -1001,7 +1022,7 @@ template bool DBinderBaseInvoker::CheckTransactionData(const dbinde } binder_size_t sessionSize = tr->sizeOfSelf - tr->buffer_size - sizeof(dbinder_transaction_data) - tr->offsets_size; - if (sessionSize * sizeof(binder_size_t) != tr->offsets_size * T::GetFlatSessionLen()) { + if (sessionSize * sizeof(binder_size_t) < tr->offsets_size * T::GetFlatSessionLen()) { return false; } } diff --git a/ipc/native/src/mock/include/dbinder_databus_invoker.h b/ipc/native/src/mock/include/dbinder_databus_invoker.h index 6594ba1..a0094f7 100644 --- a/ipc/native/src/mock/include/dbinder_databus_invoker.h +++ b/ipc/native/src/mock/include/dbinder_databus_invoker.h @@ -88,6 +88,7 @@ private: void SetCallerUid(pid_t uid) override; void SetStatus(uint32_t status) override; void SetCallerDeviceID(const std::string &deviceId) override; + void SetCallerTokenID(const uint32_t tokenId) override; int CheckAndSetCallerInfo(uint32_t listenFd, uint64_t stubIndex) override; uint32_t HasRawDataPackage(const char *data, ssize_t len); uint32_t HasCompletePackage(const char *data, uint32_t readCursor, ssize_t len); @@ -97,6 +98,7 @@ private: bool ConnectRemoteObject2Session(IRemoteObject *stubObject, uint64_t stubIndex, const std::shared_ptr sessionObject); bool AuthSession2Proxy(uint32_t handle, const std::shared_ptr Session); + bool SetTokenId(const dbinder_transaction_data *tr, uint32_t listenFd) override; private: DISALLOW_COPY_AND_MOVE(DBinderDatabusInvoker); diff --git a/ipc/native/src/mock/source/dbinder_databus_invoker.cpp b/ipc/native/src/mock/source/dbinder_databus_invoker.cpp index eb45865..a0a758b 100644 --- a/ipc/native/src/mock/source/dbinder_databus_invoker.cpp +++ b/ipc/native/src/mock/source/dbinder_databus_invoker.cpp @@ -26,6 +26,7 @@ #include "ipc_debug.h" #include "log_tags.h" #include "databus_session_callback.h" +#include "rpc_feature_set.h" namespace OHOS { using namespace OHOS::HiviewDFX; @@ -153,11 +154,17 @@ bool DBinderDatabusInvoker::AuthSession2Proxy(uint32_t handle, return false; } + std::shared_ptr feature = databusSession->GetFeatureSet(); + if (feature == nullptr) { + DBINDER_LOGE("get feature fail"); + return false; + } + MessageParcel data, reply; MessageOption option; if (!data.WriteUint32((uint32_t)(session->GetPeerPid())) || !data.WriteUint32(session->GetPeerUid()) || - !data.WriteString(session->GetPeerDeviceId())) { + !data.WriteString(session->GetPeerDeviceId()) || !data.WriteUint32(feature->featureSet)) { DBINDER_LOGE("write to MessageParcel fail"); return false; } @@ -225,13 +232,16 @@ bool DBinderDatabusInvoker::OnReceiveNewConnection(std::shared_ptr sess return false; } - if (!current->QueryIsAuth(session->GetPeerPid(), (int32_t)(session->GetPeerUid()), session->GetPeerDeviceId())) { - DBINDER_LOGE("remote device is not auth"); + auto featureSet = current->QueryIsAuth(session->GetPeerPid(), (int32_t)(session->GetPeerUid()), + session->GetPeerDeviceId()); + if (featureSet == nullptr) { + DBINDER_LOGE("query auth failed, remote device featureSet is null"); return false; } std::shared_ptr sessionObject = std::make_shared(session, session->GetPeerSessionName(), session->GetPeerDeviceId()); + sessionObject->SetFeatureSet(featureSet); if (!current->StubAttachDBinderSession(handle, sessionObject)) { DBINDER_LOGE("attach session to process skeleton failed, handle =%u", handle); @@ -662,11 +672,40 @@ void DBinderDatabusInvoker::SetCallerDeviceID(const std::string &deviceId) callerDeviceID_ = deviceId; } +void DBinderDatabusInvoker::SetCallerTokenID(const uint32_t tokenId) +{ + callerTokenID_ = tokenId; +} + bool DBinderDatabusInvoker::IsLocalCalling() { return false; } +bool DBinderDatabusInvoker::SetTokenId(const dbinder_transaction_data *tr, uint32_t listenFd) +{ + if (tr == nullptr) { + DBINDER_LOGE("set tokenid tr is null"); + return false; + } + std::shared_ptr sessionObject = QueryClientSessionObject(listenFd); + if (sessionObject == nullptr) { + DBINDER_LOGE("session is not exist for listenFd = %u", listenFd); + return false; + } + std::shared_ptr feature = sessionObject->GetFeatureSet(); + if (feature == nullptr) { + DBINDER_LOGE("feature is null"); + return false; + } + if (IsATEnable(feature->featureSet) == true) { + uint32_t bufferUseSize = tr->buffer_size + tr->offsets_size; + uint32_t tokenId = *(uint32_t *)(tr->buffer + bufferUseSize); + SetCallerTokenID(tokenId); + } + return true; +} + int DBinderDatabusInvoker::CheckAndSetCallerInfo(uint32_t listenFd, uint64_t stubIndex) { std::shared_ptr sessionObject = QueryClientSessionObject(listenFd); @@ -788,7 +827,8 @@ bool DBinderDatabusInvoker::ConnectRemoteObject2Session(IRemoteObject *stubObjec DBINDER_LOGI("fail to attach appinfo to stub index, when proxy call we check appinfo"); // attempt attach again, if failed, do nothing } - if (!current->AttachCommAuthInfo(stubObject, peerPid, peerUid, deviceId)) { + + if (!current->AttachCommAuthInfo(stubObject, peerPid, peerUid, deviceId, sessionObject->GetFeatureSet())) { DBINDER_LOGI("fail to attach comm auth info, maybe attached already"); // attempt attach again, if failed, do nothing } diff --git a/ipc/test/BUILD.gn b/ipc/test/BUILD.gn index a3ff7ee..8e6132b 100644 --- a/ipc/test/BUILD.gn +++ b/ipc/test/BUILD.gn @@ -28,6 +28,9 @@ config("ipc_test_config") { #################################group######################################### group("moduletest") { testonly = true - deps = [ "moduletest/native:moduletest" ] + deps = [ + "$SUBSYSTEM_DIR/services/dbinder/test:moduletest", + "moduletest/native:moduletest", + ] } ############################################################################### diff --git a/services/dbinder/dbinder_service/src/dbinder_service.cpp b/services/dbinder/dbinder_service/src/dbinder_service.cpp index 872f1fe..a100009 100644 --- a/services/dbinder/dbinder_service/src/dbinder_service.cpp +++ b/services/dbinder/dbinder_service/src/dbinder_service.cpp @@ -30,6 +30,7 @@ #include "dbinder_error_code.h" #include "softbus_bus_center.h" #include "dbinder_sa_death_recipient.h" +#include "rpc_feature_set.h" namespace OHOS { using namespace Communication; @@ -293,9 +294,8 @@ bool DBinderService::SendEntryToRemote(const sptr stub, uint message->head.version = VERSION_NUM; message->dBinderCode = MESSAGE_AS_INVOKER; message->transType = GetRemoteTransType(); - message->fromPort = 0; - message->toPort = 0; - message->stubIndex = static_cast(std::stoi(stub->GetServiceName().c_str())); + message->rpcFeatureSet = GetLocalRpcFeature(); + message->stubIndex = static_cast(std::atoi(stub->GetServiceName().c_str())); message->seqNumber = seqNumber; message->binderObject = stub->GetBinderObject(); message->stub = reinterpret_cast(stub.GetRefPtr()); @@ -486,6 +486,29 @@ std::string DBinderService::CreateDatabusName(int uid, int pid) return sessionName; } +bool DBinderService::HandleInvokeListenThread(IPCObjectProxy *proxy, uint64_t stubIndex, + std::string serverSessionName, struct DHandleEntryTxRx *replyMessage) +{ + if (stubIndex == 0 || serverSessionName.empty() || serverSessionName.length() > SERVICENAME_LENGTH) { + DBINDER_LOGE("stubindex or session name invalid"); + return false; + } + + replyMessage->dBinderCode = MESSAGE_AS_REPLY; + replyMessage->stubIndex = stubIndex; + replyMessage->serviceNameLength = serverSessionName.length(); + if (memcpy_s(replyMessage->serviceName, SERVICENAME_LENGTH, serverSessionName.data(), + replyMessage->serviceNameLength) != 0) { + DBINDER_LOGE("fail to copy memory"); + return false; + } + replyMessage->serviceName[replyMessage->serviceNameLength] = '\0'; + replyMessage->rpcFeatureSet = GetLocalRpcFeature() | GetRpcFeatureAck(); + + (void)AttachBusNameObject(proxy, serverSessionName); + return true; +} + bool DBinderService::OnRemoteInvokerDataBusMessage(IPCObjectProxy *proxy, struct DHandleEntryTxRx *replyMessage, std::string &remoteDeviceId, int pid, int uid) { @@ -499,11 +522,12 @@ bool DBinderService::OnRemoteInvokerDataBusMessage(IPCObjectProxy *proxy, struct return false; } + uint32_t featureSet = replyMessage->rpcFeatureSet & GetLocalRpcFeature(); MessageParcel data; MessageParcel reply; if (!data.WriteUint16(IRemoteObject::DATABUS_TYPE) || !data.WriteString(GetLocalDeviceID()) || !data.WriteUint32(pid) || !data.WriteUint32(uid) || !data.WriteString(remoteDeviceId) || - !data.WriteString(sessionName)) { + !data.WriteString(sessionName) || !data.WriteUint32(featureSet)) { DBINDER_LOGE("write to parcel fail"); return false; } @@ -514,23 +538,7 @@ bool DBinderService::OnRemoteInvokerDataBusMessage(IPCObjectProxy *proxy, struct } uint64_t stubIndex = reply.ReadUint64(); std::string serverSessionName = reply.ReadString(); - if (stubIndex == 0 || serverSessionName.empty() || serverSessionName.length() > SERVICENAME_LENGTH) { - DBINDER_LOGE("stubindex or session name invalid"); - return false; - } - - replyMessage->dBinderCode = MESSAGE_AS_REPLY; - replyMessage->stubIndex = stubIndex; - replyMessage->serviceNameLength = serverSessionName.length(); - if (memcpy_s(replyMessage->serviceName, SERVICENAME_LENGTH, serverSessionName.data(), - replyMessage->serviceNameLength) != 0) { - DBINDER_LOGE("fail to copy memory"); - return false; - } - replyMessage->serviceName[replyMessage->serviceNameLength] = '\0'; - - (void)AttachBusNameObject(proxy, serverSessionName); - return true; + return HandleInvokeListenThread(proxy, stubIndex, serverSessionName, replyMessage); } std::u16string DBinderService::GetRegisterService(binder_uintptr_t binderObject) @@ -652,8 +660,10 @@ void DBinderService::MakeSessionByReplyMessage(const struct DHandleEntryTxRx *re session->seqNumber = replyMessage->seqNumber; session->socketFd = 0; session->stubIndex = replyMessage->stubIndex; - session->toPort = replyMessage->toPort; - session->fromPort = replyMessage->fromPort; + session->rpcFeatureSet = 0; + if (IsFeatureAck(replyMessage->rpcFeatureSet) == true) { + session->rpcFeatureSet = replyMessage->rpcFeatureSet & GetLocalRpcFeature(); + } session->type = replyMessage->transType; session->serviceName = replyMessage->serviceName; diff --git a/services/dbinder/dbinder_service/src/dbinder_service_stub.cpp b/services/dbinder/dbinder_service/src/dbinder_service_stub.cpp index 0a92804..e39d53f 100644 --- a/services/dbinder/dbinder_service/src/dbinder_service_stub.cpp +++ b/services/dbinder/dbinder_service/src/dbinder_service_stub.cpp @@ -85,7 +85,8 @@ int32_t DBinderServiceStub::ProcessProto(uint32_t code, MessageParcel &data, Mes case IRemoteObject::DATABUS_TYPE: { if (!reply.WriteUint32(IRemoteObject::IF_PROT_DATABUS) || !reply.WriteUint64(session->stubIndex) || !reply.WriteString(session->serviceName) || !reply.WriteString(session->deviceIdInfo.toDeviceId) || - !reply.WriteString(session->deviceIdInfo.fromDeviceId) || !reply.WriteString(localBusName)) { + !reply.WriteString(session->deviceIdInfo.fromDeviceId) || !reply.WriteString(localBusName) || + !reply.WriteUint32(session->rpcFeatureSet)) { DBINDER_LOGE("write to parcel fail"); return DBINDER_SERVICE_PROCESS_PROTO_ERR; } diff --git a/services/dbinder/test/BUILD.gn b/services/dbinder/test/BUILD.gn index 0fc1efc..b16664b 100644 --- a/services/dbinder/test/BUILD.gn +++ b/services/dbinder/test/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (C) 2021 Huawei Device Co., Ltd. +# Copyright (C) 2022 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -162,3 +162,8 @@ group("distributedtest") { ":dbindertest_py", ] } + +group("moduletest") { + testonly = true + deps = [ "moduletest" ] +} diff --git a/services/dbinder/test/moduletest/BUILD.gn b/services/dbinder/test/moduletest/BUILD.gn new file mode 100644 index 0000000..6efa01d --- /dev/null +++ b/services/dbinder/test/moduletest/BUILD.gn @@ -0,0 +1,80 @@ +# Copyright (C) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +SUBSYSTEM_DIR = "//foundation/communication/ipc" + +# DBINDER_TEST_ROOT = "//foundation/communication/ipc/services/dbinder/test" +MODULE_OUTPUT_PATH = "ipc/services/dbinder" + +ohos_moduletest("RPCCLIENTTEST") { + module_out_path = MODULE_OUTPUT_PATH + include_dirs = [ + "include", + "${SUBSYSTEM_DIR}/utils/include", + "${SUBSYSTEM_DIR}/ipc/native/c/adapter/access_token/include", + ] + sources = [ + "src/rpc_client_test.cpp", + "src/rpc_test.cpp", + ] + configs = [ "$SUBSYSTEM_DIR:ipc_util_config" ] + deps = [ + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "dsoftbus_standard:softbus_client", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "samgr_standard:samgr_proxy", + ] +} + +ohos_moduletest("RPCSERVERTEST") { + module_out_path = MODULE_OUTPUT_PATH + include_dirs = [ + "include", + "${SUBSYSTEM_DIR}/utils/include", + ] + sources = [ + "src/rpc_server_test.cpp", + "src/rpc_test.cpp", + ] + configs = [ "$SUBSYSTEM_DIR:ipc_util_config" ] + deps = [ + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + + external_deps = [ + "dsoftbus_standard:softbus_client", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "samgr_standard:samgr_proxy", + ] +} + +############################################################################### +group("moduletest") { + testonly = true + deps = [ + ":RPCCLIENTTEST", + ":RPCSERVERTEST", + ] +} + +############################################################################### + diff --git a/services/dbinder/test/moduletest/include/rpc_test.h b/services/dbinder/test/moduletest/include/rpc_test.h new file mode 100644 index 0000000..6b724fe --- /dev/null +++ b/services/dbinder/test/moduletest/include/rpc_test.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_RPC_FOO_TEST_H +#define OHOS_RPC_FOO_TEST_H + +#include +#include +#include "iremote_broker.h" +#include "iremote_proxy.h" +#include "iremote_stub.h" +#include "hilog/log.h" +#include "log_tags.h" + +namespace OHOS { +class IFoo : public IRemoteBroker { +public: + enum FooInterFaceId { + GET_FOO_NAME = 0, + SEND_ASYNC_REPLY = 1, + SEND_WRONG_REPLY = 2, + GET_TOKENID = 3, + }; + virtual std::string GetFooName() = 0; + virtual void SendAsyncReply(int &reply) = 0; + virtual int TestNestingSend(int sendCode) = 0; + virtual uint32_t TestAccessToken(void) = 0; +public: + DECLARE_INTERFACE_DESCRIPTOR(u"test.ipc.IFoo"); +}; + +class FooStub : public IRemoteStub { +public: + virtual ~FooStub(); + int OnRemoteRequest(uint32_t code, + MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + std::string GetFooName() override; + void SendAsyncReply(int &reply) override; + int WaitForAsyncReply(int timeout); + static void CleanDecTimes(); + static int GetDecTimes(); + int TestNestingSend(int sendCode) override; + uint32_t TestAccessToken(void) override; +public: + static std::mutex decTimeMutex_; + static int decTimes_; +private: + int asyncReply_ = { 0 }; + std::mutex mutex_; + std::condition_variable cv_; + static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "FooStub" }; +}; + +class FooProxy : public IRemoteProxy { +public: + explicit FooProxy(const sptr &impl); + ~FooProxy() = default; + std::string GetFooName() override; + void SendAsyncReply(int &reply) override; + int TestNestingSend(int sendCode) override; + uint32_t TestAccessToken(void) override; +private: + static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "FooProxy" }; + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS +#endif // OHOS_RPC_FOO_TEST_H + diff --git a/services/dbinder/test/moduletest/src/rpc_client_test.cpp b/services/dbinder/test/moduletest/src/rpc_client_test.cpp new file mode 100644 index 0000000..fe07921 --- /dev/null +++ b/services/dbinder/test/moduletest/src/rpc_client_test.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "system_ability_definition.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "softbus_bus_center.h" +#include "ipc_skeleton.h" +#include "ipc_object_proxy.h" +#include "rpc_test.h" +#include "access_token_adapter.h" +#include "log_tags.h" + +namespace OHOS { +#ifndef TITLE +#define TITLE __PRETTY_FUNCTION__ +#endif + +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::HiviewDFX; + +static constexpr HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "RPCClientTest" }; +#define DBINDER_LOGE(fmt, args...) \ + (void)OHOS::HiviewDFX::HiLog::Error(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args) +#define DBINDER_LOGI(fmt, args...) \ + (void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args) + +static std::string g_deviceId; +class RPCClientTest : public testing::Test { +public: + static constexpr int saId = RPC_TEST_SERVICE; + static constexpr char DBINDER_PKG_NAME[] = "DBinderService"; + static constexpr int NODE_NUM = 4; + static void SetUpTestCase(void); + static void TearDownTestCase(void); +}; + +void RPCClientTest::SetUpTestCase() +{ + NodeBasicInfo *nodeInfo[NODE_NUM]; + int32_t infoNum = NODE_NUM; + int32_t ret = GetAllNodeDeviceInfo(DBINDER_PKG_NAME, nodeInfo, &infoNum); + if (ret != 0) { + DBINDER_LOGE("get local node ret %{public}d", ret); + return; + } + if (infoNum == 0) { + DBINDER_LOGE("get no online nodes"); + return; + } + g_deviceId = nodeInfo[0]->networkId; + DBINDER_LOGI("get deviceid %{public}s", g_deviceId.c_str()); +} + +void RPCClientTest::TearDownTestCase() {} + +HWTEST_F(RPCClientTest, function_test_001, TestSize.Level1) +{ + DBINDER_LOGI("Start RPCClient Testcase001"); + // service instance + auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + EXPECT_TRUE(saMgr != nullptr); + + sptr object = saMgr->GetSystemAbility(IPC_TEST_SERVICE, g_deviceId); + ASSERT_TRUE(object != nullptr); + + sptr testService = iface_cast(object); + ASSERT_TRUE(testService != nullptr); + + uint32_t tokenId = RpcGetSelfTokenID(); + uint32_t getTokenId = testService->TestAccessToken(); + ASSERT_EQ(tokenId, getTokenId); +} +} \ No newline at end of file diff --git a/services/dbinder/test/moduletest/src/rpc_server_test.cpp b/services/dbinder/test/moduletest/src/rpc_server_test.cpp new file mode 100644 index 0000000..3a40588 --- /dev/null +++ b/services/dbinder/test/moduletest/src/rpc_server_test.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "system_ability_definition.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "ipc_skeleton.h" +#include "rpc_test.h" +#include "log_tags.h" + +namespace OHOS { +#ifndef TITLE +#define TITLE __PRETTY_FUNCTION__ +#endif + +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::HiviewDFX; + +static constexpr HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "RPCServerTest" }; +#define DBINDER_LOGE(fmt, args...) \ + (void)OHOS::HiviewDFX::HiLog::Error(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args) +#define DBINDER_LOGI(fmt, args...) \ + (void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args) + +class RPCServerTest : public testing::Test { +public: + static constexpr int saId = RPC_TEST_SERVICE; + static void SetUpTestCase(void); + static void TearDownTestCase(void); +}; + +void RPCServerTest::SetUpTestCase() {} + +void RPCServerTest::TearDownTestCase() {} + +HWTEST_F(RPCServerTest, function_test_001, TestSize.Level1) +{ + DBINDER_LOGI("Start RPCServer Testcase001"); + auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + EXPECT_TRUE(saMgr != nullptr); + + ISystemAbilityManager::SAExtraProp saExtra; + saExtra.isDistributed = true; // 设置为分布式SA + int result = saMgr->AddSystemAbility(saId, new FooStub(), saExtra); + ASSERT_EQ(result, 0); + + IPCSkeleton::JoinWorkThread(); +} +} \ No newline at end of file diff --git a/services/dbinder/test/moduletest/src/rpc_test.cpp b/services/dbinder/test/moduletest/src/rpc_test.cpp new file mode 100644 index 0000000..6b750a8 --- /dev/null +++ b/services/dbinder/test/moduletest/src/rpc_test.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rpc_test.h" +#include "ipc_skeleton.h" +#include "ipc_debug.h" +#include "ipc_types.h" + +namespace OHOS { +std::mutex FooStub::decTimeMutex_; +int FooStub::decTimes_ = 0; + +int FooStub::OnRemoteRequest(uint32_t code, + MessageParcel& data, MessageParcel& reply, MessageOption& option) +{ + int result = ERR_NONE; + + switch (code) { + case GET_FOO_NAME: { + ZLOGI(LABEL, "%{public}s:called\n", __func__); + reply.WriteString(GetFooName()); + break; + } + case SEND_ASYNC_REPLY: { + int32_t replyData = data.ReadInt32(); + SendAsyncReply(replyData); + break; + } + case SEND_WRONG_REPLY: { + return TestNestingSend(data.ReadInt32()); + } + case GET_TOKENID: { + uint32_t tokenId = TestAccessToken(); + reply.WriteUint32(tokenId); + break; + } + default: + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } + + return result; +} + +std::string FooStub::GetFooName() +{ + return "ReallFoo"; +} + +int FooStub::WaitForAsyncReply(int timeout) +{ + asyncReply_ = 0; + std::unique_lock lck(mutex_); + cv_.wait_for(lck, std::chrono::milliseconds(timeout), [&]() { + return asyncReply_ != 0; + }); + return asyncReply_; +} + +void FooStub::SendAsyncReply(int &replyValue) +{ + std::unique_lock lck(mutex_); + asyncReply_ = replyValue; + cv_.notify_all(); +} + +FooStub::~FooStub() +{ + std::unique_lock lck(decTimeMutex_); + decTimes_++; +} + +void FooStub::CleanDecTimes() +{ + std::unique_lock lck(decTimeMutex_); + decTimes_ = 0; +} + +int FooStub::GetDecTimes() +{ + std::unique_lock lck(decTimeMutex_); + return decTimes_; +} + +int FooStub::TestNestingSend(int sendCode) +{ + return sendCode; +} + +uint32_t FooStub::TestAccessToken(void) +{ + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + return tokenId; +} + +FooProxy::FooProxy(const sptr &impl) + : IRemoteProxy(impl) +{ +} + +std::string FooProxy::GetFooName() +{ + ZLOGI(LABEL, "%{public}s:called\n", __func__); + MessageParcel data, reply; + MessageOption option; + Remote()->SendRequest(GET_FOO_NAME, data, reply, option); + return reply.ReadString(); +} + +void FooProxy::SendAsyncReply(int &replyValue) +{ + ZLOGI(LABEL, "%{public}s:called\n", __func__); + MessageParcel data, reply; + MessageOption option = { MessageOption::TF_ASYNC }; + data.WriteInt32(replyValue); + Remote()->SendRequest(SEND_ASYNC_REPLY, data, reply, option); +} + +int FooProxy::TestNestingSend(int sendCode) +{ + MessageOption option; + MessageParcel dataParcel, replyParcel; + if (!dataParcel.WriteInt32(sendCode)) { + return -1; + } + int error = Remote()->SendRequest(SEND_WRONG_REPLY, dataParcel, replyParcel, option); + ZLOGE(LABEL, "send foo result = %{public}d", error); + return error; +} + +uint32_t FooProxy::TestAccessToken(void) +{ + MessageOption option; + MessageParcel dataParcel, replyParcel; + int err = Remote()->SendRequest(GET_TOKENID, dataParcel, replyParcel, option); + if (err != 0) { + ZLOGE(LABEL, "get tokenid failed %{public}d", err); + return 0; + } + return replyParcel.ReadUint32(); +} +} // namespace OHOS \ No newline at end of file -- GitLab