diff --git a/include/ipc_base.h b/include/ipc_base.h new file mode 100644 index 0000000000000000000000000000000000000000..9be46546731a610cf425b7a96e8b397eda924245 --- /dev/null +++ b/include/ipc_base.h @@ -0,0 +1,78 @@ +#ifndef _IPC_BASE_H_ +#define _IPC_BASE_H_ + +#include +#include +#include +#include +#include +#include + +#define IPC_LOG(fmt, args...) \ + printf("[IPC LOG %s:%u]" fmt, __FILE__, __LINE__, ##args) +#define IPC_DEBUG(fmt, args...) \ +// printf("[IPC DEBUG %s:%u]" rmt, __FILE__, __LINE__, ##args) + +extern key_t g_client_server_shmKey; +extern key_t g_device_auth_shmKey; + +const int IPC_SHM_FLAG = IPC_CREAT | 0666; + +const size_t DATA_SIZE = 0x20000; + +const int32_t GET_SA_REQUEST_CODE = 2; +const int32_t WIFI_DEVICE_ABILITY_ID = 1125; +const int32_t WIFI_P2P_ABILITY_ID = 1128; + +struct IpcShmData { + size_t inputSz; + size_t outputSz; + char inputData[DATA_SIZE]; + char outputData[DATA_SIZE]; + volatile bool needReply; + uint32_t requestCode; + volatile bool containFd; + volatile bool containHandle; + unsigned long long handle; + std::atomic< bool > isProcessing; + bool deadNotice; +}; + +static inline IpcShmData *OpenShmCommon(key_t shmKey, int flag) +{ + int shmFd = shmget(shmKey, sizeof(IpcShmData), flag); + if (shmFd < 0) { + IPC_LOG("Get shm failed, errno=%d\n", errno); + return nullptr; + } + void *shmPtr = shmat(shmFd, 0, 0); + if (shmPtr == (void *)-1) { + IPC_LOG("Map shm failed\n"); + return nullptr; + } + return (IpcShmData *)shmPtr; +} + +static inline IpcShmData *OpenShm(key_t shmKey) +{ + return OpenShmCommon(shmKey, IPC_SHM_FLAG); +} + +static inline IpcShmData *OpenShmExcl(key_t shmKey) +{ + return OpenShmCommon(shmKey, IPC_SHM_FLAG | IPC_EXCL); +} + +static inline key_t HandleToKey(unsigned long long handle) +{ + key_t key = handle >> 32; + key ^= handle & 0xFFFFFFFF; + return key; +} + +static inline void HandleToAddr(char *addr, unsigned long long handle) +{ + sprintf(addr, "/tmp/%llx.ipc.socket", handle); +} + +#endif // _IPC_BASE_H_ diff --git a/include/ipc_center.h b/include/ipc_center.h new file mode 100644 index 0000000000000000000000000000000000000000..999bf54edad8931a391195168b9cbe3befa650e2 --- /dev/null +++ b/include/ipc_center.h @@ -0,0 +1,20 @@ +#ifndef _IPC_CENTER_H_ +#define _IPC_CENTER_H_ + +#include "iremote_object.h" +#include "ipc_object_stub.h" + +namespace OHOS { + +class IpcCenter { +public: + static bool ShmInit(key_t ShmKey); + static bool Init(bool isServer, IPCObjectStub *stub); + static bool ThreadCreate(IPCObjectStub *stub); + static void ProcessHandle(key_t ShmKey, IPCObjectStub *ipcStub); + static size_t threadNum_; +}; + +} // namespace OHOS + +#endif //_IPC_CENTER_H_ diff --git a/include/ipc_object_proxy.h b/include/ipc_object_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..a130e694bd265a157297f05b4c61c13542eeadd2 --- /dev/null +++ b/include/ipc_object_proxy.h @@ -0,0 +1,25 @@ +#ifndef _IPC_OBJECT_PROXY_H_ +#define _IPC_OBJECT_PROXY_H_ + +#include "ipc_base.h" +#include "iremote_object.h" + +namespace OHOS { + +class IPCObjectProxy : public IRemoteObject { +public: + IPCObjectProxy(unsigned long long handle); + ~IPCObjectProxy(); + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + bool AddDeathRecipient(const sptr< DeathRecipient > &recipient) override; + void SendObituary(); +private: + key_t sendShmKey_; + const char *socketAddr_; + int recvFd_; + sptr< DeathRecipient > deathRecipient_; +}; + +}; // namespace OHOS + +#endif // _IPC_OBJECT_PROXY_H_ \ No newline at end of file diff --git a/include/ipc_object_stub.h b/include/ipc_object_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..a1306ab176081a334f22740879c6db92db9d67cb --- /dev/null +++ b/include/ipc_object_stub.h @@ -0,0 +1,24 @@ +#ifndef _IPC_OBJECT_STUB_H_ +#define _IPC_OBJECT_STUB_H_ + +#include + +#include "iremote_object.h" + +namespace OHOS { + +class IPCObjectStub : public IRemoteObject { +public: + IPCObjectStub(); + ~IPCObjectStub(); + virtual int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); + void CreateThread(key_t shmKey); + void SendDeadNotification(); + volatile bool needStop_; + const char *sendAddr_; + int recvFd_; +}; + +} // namespace OHOS + +#endif // _IPC_OBJECT_STUB_H_ \ No newline at end of file diff --git a/include/ipc_proxy_manager.h b/include/ipc_proxy_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..0dc0d672401f224804d8d3ff57b26cc513dec75b --- /dev/null +++ b/include/ipc_proxy_manager.h @@ -0,0 +1,20 @@ +#ifndef _IPC_PROXY_MANAGER_H_ +#define _IPC_PROXY_MANAGER_H_ + +#include +#include +#include "ipc_object_proxy.h" + +namespace OHOS { +class IPCProxyManager { +public: + static sptr< IPCObjectProxy > FindOrNewProxy(unsigned long long handle); + static void CleanProxy(unsigned long long handle); +private: + static std::map< unsigned long long, sptr< IPCObjectProxy > > proxyMap_; + static std::mutex mutex_; +}; + +}; + +#endif // _IPC_PROXY_MANAGER_H_ \ No newline at end of file diff --git a/include/ipc_skeleton.h b/include/ipc_skeleton.h new file mode 100644 index 0000000000000000000000000000000000000000..310624364cc18118e2aab8d17a3d26ace0797128 --- /dev/null +++ b/include/ipc_skeleton.h @@ -0,0 +1,35 @@ +#ifndef _IPC_SKELETON_H_ +#define _IPC_SKELETON_H_ + +#include +#include + +#include "parcel.h" +#include "refbase.h" + +namespace OHOS { + +class IRemoteObject; + +class IPCSkeleton { +public: + IPCSkeleton() = default; + ~IPCSkeleton() = default; + static pid_t GetCallingPid(); + static uid_t GetCallingUid(); + static sptr< IRemoteObject > GetContextObject(); + static bool SetContextObject(sptr< IRemoteObject > &object); + static int SocketListening(const char *addr); + static int SocketReadFd(int socketFd); + static bool SocketWriteFd(const char *addr, int fd); + static bool SetDeviceAuthObj(sptr< IRemoteObject > obj); + static sptr< IRemoteObject > GetDeviceAuthObj(); + +private: + static sptr< IRemoteObject > obj_; + static sptr< IRemoteObject > deviceAuthObj_; +}; + +} // namespace OHOS + +#endif // _IPC_SKELETON_H_ diff --git a/include/ipc_socket_manager.h b/include/ipc_socket_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..b8f86ac7c988d7662875f27d5d7efa407dd7157d --- /dev/null +++ b/include/ipc_socket_manager.h @@ -0,0 +1,20 @@ +#ifndef _IPC_SOCKET_MANAGER_H_ +#define _IPC_SOCKET_MANAGER_H_ + +#include +#include + +namespace OHOS { + +class IPCSocketManager { +public: + static void InsertSocketFd(unsigned long long handle, int socketFd); + static int FindSocketFd(unsigned long long handle); +private: + static std::map< unsigned long long, int > socketFdMap_; + static std::mutex mutex_; +}; + +} // namespace OHOS + +#endif // _IPC_SOCKET_MANAGER_H_ \ No newline at end of file diff --git a/include/ipc_stub_manager.h b/include/ipc_stub_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..a2533b53fd837f3114ca3ac0253f87f5b1262adb --- /dev/null +++ b/include/ipc_stub_manager.h @@ -0,0 +1,20 @@ +#ifndef _IPC_STUB_MANAGER_H_ +#define _IPC_STUB_MANAGER_H_ + +#include +#include +#include "ipc_object_stub.h" + +namespace OHOS { +class IPCStubManager { +public: + static unsigned long long GetHandleNum(); + static void InsertStub(unsigned long long handle, sptr< IPCObjectStub > stub); +private: + static std::map< unsigned long long, sptr< IPCObjectStub > > stubMap_; + static std::mutex mutex_; +}; + +}; + +#endif // _IPC_STUB_MANAGER_H_ \ No newline at end of file diff --git a/include/ipc_types.h b/include/ipc_types.h new file mode 100644 index 0000000000000000000000000000000000000000..80f50cef2654013be524a46bde0ad9ca914df6e3 --- /dev/null +++ b/include/ipc_types.h @@ -0,0 +1 @@ +/* empty head files for compile */ diff --git a/include/iremote_broker.h b/include/iremote_broker.h new file mode 100644 index 0000000000000000000000000000000000000000..e6f54250493c6bdff1959ac235d193eec3139062 --- /dev/null +++ b/include/iremote_broker.h @@ -0,0 +1,15 @@ +#ifndef _IREMOTE_BROKER_H +#define _IREMOTE_BROKER_H + +#ifdef __cplusplus + +namespace OHOS { + +template class BrokerDelegator { +}; + +}; + +#endif + +#endif diff --git a/include/iremote_object.h b/include/iremote_object.h new file mode 100644 index 0000000000000000000000000000000000000000..ad7c12866c31605c9ff1df2d7ef44e3262cf9305 --- /dev/null +++ b/include/iremote_object.h @@ -0,0 +1,47 @@ +#ifndef _IPC_REMOTE_OBJECT_H_ +#define _IPC_REMOTE_OBJECT_H_ + +#include "message_parcel.h" +#include "message_option.h" + +namespace OHOS { + +class IRemoteBroker : public virtual RefBase { +public: + IRemoteBroker() = default; + virtual ~IRemoteBroker() override = default; + virtual sptr< IRemoteObject > AsObject() = 0; + static inline sptr< IRemoteBroker > AsImplement(const sptr< IRemoteObject > &object) + { + return nullptr; + } +}; + +#define DECLARE_INTERFACE_DESCRIPTOR(DESCRIPTOR) \ + static inline const std::u16string metaDescriptor_ = {DESCRIPTOR} ; \ + static inline const std::u16string &GetDescriptor() \ + { \ + return metaDescriptor_; \ + } + +class IRemoteObject : public virtual Parcelable { +public: + IRemoteObject(); + ~IRemoteObject(); + class DeathRecipient : public RefBase { + public: + virtual void OnRemoteDied(const wptr< IRemoteObject > &object) {} + }; + + virtual int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option); + virtual bool AddDeathRecipient(const sptr< DeathRecipient > &recipient); + virtual bool RemoveDeathRecipient(const sptr< DeathRecipient > &recipient); + virtual bool Marshalling(Parcel &parcel) const override; + unsigned long long GetHandle(); + unsigned long long handle_; + bool isDSoftBusObj; +}; + +} // namespace OHOS + +#endif // _IPC_REMOTE_OBJECT_H_ diff --git a/include/iremote_parcel.h b/include/iremote_parcel.h new file mode 100644 index 0000000000000000000000000000000000000000..80f50cef2654013be524a46bde0ad9ca914df6e3 --- /dev/null +++ b/include/iremote_parcel.h @@ -0,0 +1 @@ +/* empty head files for compile */ diff --git a/include/iremote_proxy.h b/include/iremote_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..4078c3562679d837c85583a09fe9026d81f95b96 --- /dev/null +++ b/include/iremote_proxy.h @@ -0,0 +1,42 @@ +#ifndef OHOS_IPC_IREMOTE_PROXY_H +#define OHOS_IPC_IREMOTE_PROXY_H + +#include "ipc_skeleton.h" + +namespace OHOS { +template class IRemoteProxy : public INTERFACE { +public: + explicit IRemoteProxy(const sptr &object); + ~IRemoteProxy() override = default; + sptr Remote(); + +protected: + sptr AsObject() override; + +private: + const sptr remoteObj_; +}; + +template +sptr IRemoteProxyremoteObj_ = nullptr; + +template +IRemoteProxy::IRemoteProxy(const sptr &object) : remoteObj_(object) {} + +template +sptr IRemoteProxy::AsObject() +{ + if (remoteObj_ != nullptr) { + return remoteObj_; + } + return IPCSkeleton::GetContextObject(); +} + +template +sptr IRemoteProxy::Remote() +{ + return AsObject(); +} + +} // namespece OHOS +#endif // OHOS_IPC_IREMOTE_PROXY_H \ No newline at end of file diff --git a/include/iremote_stub.h b/include/iremote_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..3b5184f9ac1ffe7243e65774fd531a6b2fee5c38 --- /dev/null +++ b/include/iremote_stub.h @@ -0,0 +1,27 @@ +#ifndef _IPC_IREMOTE_STUB_H_ +#define _IPC_IREMOTE_STUB_H_ + +#include "ipc_object_stub.h" + +namespace OHOS { + +template< typename INTERFACE > +class IRemoteStub : public IPCObjectStub, public INTERFACE { +public: + IRemoteStub(); + virtual ~IRemoteStub() = default; + sptr< IRemoteObject > AsObject() override; +}; + +template< typename INTERFACE > +IRemoteStub< INTERFACE >::IRemoteStub() : IPCObjectStub() {} + +template< typename INTERFACE > +sptr< IRemoteObject > IRemoteStub< INTERFACE >::AsObject() +{ + return this; +} + +} // namespace OHOS + +#endif // _IPC_IREMOTE_STUB_H_ \ No newline at end of file diff --git a/include/message_option.h b/include/message_option.h new file mode 100644 index 0000000000000000000000000000000000000000..e5904b92bdd0156cbad0446bc8e2590870ae5901 --- /dev/null +++ b/include/message_option.h @@ -0,0 +1,10 @@ +#ifndef _MESSAGE_OPTION_H_ +#define _MESSAGE_OPTION_H_ + +namespace OHOS { + +class MessageOption {}; + +} + +#endif // _MESSAGE_OPTION_H_ \ No newline at end of file diff --git a/include/message_parcel.h b/include/message_parcel.h new file mode 100644 index 0000000000000000000000000000000000000000..5390aea10de42cac0ff413ba3dd58d5d91f72efc --- /dev/null +++ b/include/message_parcel.h @@ -0,0 +1,31 @@ +#ifndef _MESSAGE_PARCEL_H_ +#define _MESSAGE_PARCEL_H_ + +#include "parcel.h" +#include "refbase.h" + +namespace OHOS { + +class IRemoteObject; +class MessageParcel : public Parcel { +public: + MessageParcel(); + ~MessageParcel(); + bool WriteFileDescriptor(int fd); + int ReadFileDescriptor(); + bool WriteRawData(const void *data, size_t size); + const void *ReadRawData(size_t size); + bool ContainFileDescriptors() const; + sptr< IRemoteObject > ReadRemoteObject(); + bool WriteRemoteObject(const sptr< IRemoteObject > &object); + bool ContainRemoteObject(); + unsigned long long RemoteObjectHandle_; + bool isContainHandle_; +private: + static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M + int fd_; +}; + +} //namespace OHOS + +#endif // _MESSAGE_PARCEL_H_ diff --git a/include/system_ability.h b/include/system_ability.h new file mode 100644 index 0000000000000000000000000000000000000000..8d893481a4e54e88adc11b98fcf9a7b96612ddd7 --- /dev/null +++ b/include/system_ability.h @@ -0,0 +1,44 @@ +#ifndef _SYSTEM_ABILITY_H +#define _SYSTEM_ABILITY_H + +#ifdef __cplusplus +//#include +//#include +#include +//#include +#include "parcel.h" + +#define DECLARE_SYSTEM_ABILITY(className) \ + public: \ + virtual std::string GetClassName() override { \ + return #className; \ + } + +#define DECLARE_BASE_SYSTEM_ABILITY(className) \ + public: \ + virtual std::string GetClassName() = 0; + +namespace OHOS { + +#define REGISTER_SYSTEM_ABILITY_BY_ID(abilityClassName, systemAbilityId, runOnCreate) \ + const bool abilityClassName##_##RegisterResult = \ + SystemAbility::MakeAndRegisterAbility(new abilityClassName(systemAbilityId, runOnCreate)); + +class IRemoteObject; + +class SystemAbility { + DECLARE_BASE_SYSTEM_ABILITY(SystemAbility); + public: + static bool MakeAndRegisterAbility(SystemAbility* systemAbility) {return true;} + bool Publish(sptr systemAbility) {return true;} + protected: + SystemAbility(bool runOnCreate = false) {} + SystemAbility(int32_t systemAbilityId, bool runOnCreate = false) {} + virtual void OnStart() = 0; + virtual void OnStop() = 0; +}; + +}; +#endif + +#endif diff --git a/include/system_ability_definition.h b/include/system_ability_definition.h new file mode 100644 index 0000000000000000000000000000000000000000..5634882e1a200e00082bafbf2a36a074a47ff922 --- /dev/null +++ b/include/system_ability_definition.h @@ -0,0 +1,15 @@ +#ifndef _SYSTEM_ABILITY_DEF_H +#define _SYSTEM_ABILITY_DEF_H + +#ifdef __cplusplus + +namespace OHOS { + +enum { + SOFTBUS_SERVER_SA_ID = 4700, +}; + +}; +#endif + +#endif diff --git a/ipc_center.cpp b/ipc_center.cpp new file mode 100644 index 0000000000000000000000000000000000000000..582a5559ea9345bdf7381032d23840da33b18339 --- /dev/null +++ b/ipc_center.cpp @@ -0,0 +1,151 @@ +#include +#include + +#include "ipc_base.h" +#include "ipc_center.h" +#include "ipc_skeleton.h" +#include "ipc_socket_manager.h" +#include "ipc_proxy_manager.h" + +namespace OHOS { + +static const char *IPC_SERVER_SOCKET_ADDR = "/tmp/ipc.socket.server"; +static const char *IPC_CLIENT_SOCKET_ADDR = "/tmp/ipc.socket.client"; + +size_t IpcCenter::threadNum_ = 0; + +bool IpcCenter::ShmInit(key_t shmKey) +{ + IpcShmData *shmPtr = OpenShm(shmKey); + if (shmPtr == nullptr) { + IPC_LOG("Create shm with key=0x%x\n", shmKey); + return false; + } + shmPtr->needReply = false; + shmPtr->containFd = false; + shmPtr->isProcessing = false; + shmPtr->deadNotice = false; + shmdt((void *)shmPtr); + return true; +} + +bool IpcCenter::Init(bool isServer, IPCObjectStub *stub) +{ + if (!isServer) { + IPC_LOG("Only the server can call this interface\n"); + return false; + } + + if (stub == nullptr) { + IPC_LOG("Invalid stub\n"); + return false; + } + + if (isServer && !ShmInit(g_client_server_shmKey)) { + IPC_LOG("Shm init failed\n"); + return false; + } + + if (isServer && !ShmInit(g_device_auth_shmKey)) { + IPC_LOG("Device auth shm init failed\n"); + return false; + } + + if (stub->recvFd_ >= 0) { + close(stub->recvFd_); + } + + stub->recvFd_ = IPCSkeleton::SocketListening(IPC_SERVER_SOCKET_ADDR); + if (stub->recvFd_ < 0) { + IPC_LOG("Starting socket listen failed\n"); + return false; + } + + IPCSocketManager::InsertSocketFd(0, stub->recvFd_); + stub->sendAddr_ = IPC_CLIENT_SOCKET_ADDR; + stub->handle_ = 0; + + return ThreadCreate(stub); +} + +void IpcCenter::ProcessHandle(key_t shmKey, IPCObjectStub *ipcStub) +{ + IpcShmData *shmPtr = OpenShm(shmKey); + if (shmPtr == nullptr) { + IPC_LOG("Open shm failed"); + return; + } + IPC_DEBUG("STUB LISTENING with handle=%llx\n", ipcStub->handle_); + do { + while (!shmPtr->needReply) { + usleep(10); + if (ipcStub->needStop_) { + IPC_LOG("STUB LISTENING END with handle=%llx\n", ipcStub->handle_); + shmdt((void*)shmPtr); + return; + } + } + + if (shmPtr->deadNotice) { + if (ipcStub->handle_) { + IPC_LOG("Client received a wrong notice\n"); + shmdt((void*)shmPtr); + return; + } + IPCProxyManager::CleanProxy(shmPtr->handle); + shmPtr->deadNotice = false; + shmPtr->needReply = false; + continue; + } + + IPC_DEBUG("PROCESSING REMOTE REQUEST with handle=%llx\n", ipcStub->handle_); + MessageParcel data, reply; + MessageOption option; + data.WriteUnpadBuffer(shmPtr->inputData, shmPtr->inputSz); + if (shmPtr->containFd) { + shmPtr->containFd = false; + if (!data.WriteFileDescriptor(IPCSkeleton::SocketReadFd(ipcStub->recvFd_))) { + IPC_LOG("Process file descriptor failed\n"); + shmdt((void *)shmPtr); + return; + } + } + if (shmPtr->containHandle) { + data.RemoteObjectHandle_ = shmPtr->handle; + data.isContainHandle_ = true; + shmPtr->containHandle = false; + } + ipcStub->OnRemoteRequest(shmPtr->requestCode, data, reply, option); + shmPtr->outputSz = reply.GetDataSize(); + if (shmPtr->outputSz > DATA_SIZE) { + IPC_LOG("Callback data overflow!\n"); + } + memcpy(shmPtr->outputData, (void*)reply.GetData(), shmPtr->outputSz); + if (reply.ContainFileDescriptors()) { + if (!IPCSkeleton::SocketWriteFd(ipcStub->sendAddr_, reply.ReadFileDescriptor())) { + IPC_LOG("Send file descriptor in reply failed\n"); + shmdt((void *)shmPtr); + return; + } + shmPtr->containFd = true; + } + if (reply.ContainRemoteObject()) { + shmPtr->handle = reply.RemoteObjectHandle_; + shmPtr->containHandle = true; + } + shmPtr->needReply = false; + IPC_DEBUG("IPC STUB PROCESS END with handle=%llx\n", ipcStub->handle_); + } while (!ipcStub->needStop_); + IPC_DEBUG("STUB LISTENING END with handle=%llx\n", ipcStub->handle_); + shmdt((void*)shmPtr); +} + +bool IpcCenter::ThreadCreate(IPCObjectStub *stub) +{ + ++threadNum_; + std::thread new_thread(std::bind(&IpcCenter::ProcessHandle, g_client_server_shmKey, stub)); + new_thread.detach(); + return true; +} + +} // namespace OHOS diff --git a/ipc_object_proxy.cpp b/ipc_object_proxy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8368e951c0725a84405cf8a680857cf3e8f23762 --- /dev/null +++ b/ipc_object_proxy.cpp @@ -0,0 +1,101 @@ +#include "ipc_skeleton.h" +#include "ipc_object_proxy.h" +#include "ipc_socket_manager.h" + +namespace OHOS { + +static const char *IPC_CLIENT_SOCKET_ADDR = "/tmp/ipc.socket.client"; + +IPCObjectProxy::IPCObjectProxy(unsigned long long handle) : + socketAddr_(IPC_CLIENT_SOCKET_ADDR), recvFd_(-1), deathRecipient_(nullptr) +{ + IPC_LOG("INSERT PROXY with handle=%llx\n", handle); + handle_ = handle; + sendShmKey_ = HandleToKey(handle); +} + +IPCObjectProxy::~IPCObjectProxy() {} + +int IPCObjectProxy::SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + IpcShmData *shmPtr = NULL; + + if (code == GET_SA_REQUEST_CODE || (code >= WIFI_DEVICE_ABILITY_ID && code <= WIFI_P2P_ABILITY_ID)) { + reply.isContainHandle_ = true; + reply.RemoteObjectHandle_ = 0; + return 0; + } + + shmPtr = OpenShm(sendShmKey_); + if (shmPtr == nullptr) { + IPC_LOG("Open Stub shm failed\n"); + return -1; + } + + IPC_DEBUG("WAITING FOR PREVIOUS IPC\n"); + + // waiting previous ipc + while (shmPtr->needReply); + + IPC_DEBUG("SENDING REQUEST with code=%u\n", code); + + shmPtr->requestCode = code; + shmPtr->inputSz = data.GetDataSize(); + if (shmPtr->inputSz > DATA_SIZE) { + IPC_LOG("Sending data overflow!"); + } + memcpy(shmPtr->inputData, (void *)data.GetData(), shmPtr->inputSz); + if (data.ContainFileDescriptors()) { + IPC_DEBUG("SENDING FD\n"); + shmPtr->containFd = true; + if (!IPCSkeleton::SocketWriteFd(socketAddr_, data.ReadFileDescriptor())) { + IPC_LOG("Send File Descriptor failed\n"); + shmdt((void*)shmPtr); + return -1; + } + } + if (data.ContainRemoteObject()) { + shmPtr->containHandle = true; + shmPtr->handle = data.RemoteObjectHandle_; + } + shmPtr->needReply = true; + + IPC_DEBUG("WAITING STUB REPLY with handle=%llx\n", handle_); + + // waiting receiver reply + while (shmPtr->needReply); + IPC_DEBUG("RECEIVED DATA FROM REMOTE with code=%u\n", code); + + reply.WriteUnpadBuffer(shmPtr->outputData, shmPtr->outputSz); + if (shmPtr->containFd) { + if (!reply.WriteFileDescriptor(IPCSkeleton::SocketReadFd(IPCSocketManager::FindSocketFd(1)))) { + IPC_LOG("Receive reply fd failed"); + shmdt((void *)shmPtr); + return -1; + } + shmPtr->containFd = false; + } + if (shmPtr->containHandle) { + reply.isContainHandle_ = true; + reply.RemoteObjectHandle_ = shmPtr->handle; + shmPtr->containHandle = false; + } + shmdt((void *)shmPtr); + return 0; +} + +bool IPCObjectProxy::AddDeathRecipient(const sptr< DeathRecipient > &recipient) +{ + deathRecipient_ = recipient; + return true; +} + +void IPCObjectProxy::SendObituary() +{ + if (deathRecipient_ != nullptr) { + deathRecipient_->OnRemoteDied(this); + deathRecipient_ = nullptr; + } +} + +} // namespace OHOS \ No newline at end of file diff --git a/ipc_object_stub.cpp b/ipc_object_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f7498309d859c0c957b0b043022706756c926fa --- /dev/null +++ b/ipc_object_stub.cpp @@ -0,0 +1,69 @@ +#include + +#include "ipc_base.h" +#include "ipc_center.h" +#include "ipc_skeleton.h" +#include "ipc_stub_manager.h" +#include "ipc_object_stub.h" +#include "ipc_socket_manager.h" + +namespace OHOS { + +static const char *IPC_SERVER_SOCKET_ADDR = "/tmp/ipc.socket.server"; +static const char *IPC_CLIENT_SOCKET_ADDR = "/tmp/ipc.socket.client"; + +IPCObjectStub::IPCObjectStub() : needStop_(false) +{ + handle_ = getpid(); + handle_ = (handle_ << 32) | IPCStubManager::GetHandleNum(); + IPCStubManager::InsertStub(handle_, this); + key_t shmKey = HandleToKey(handle_); + IpcCenter::ShmInit(shmKey); + sendAddr_ = IPC_SERVER_SOCKET_ADDR; + CreateThread(shmKey); +} + +IPCObjectStub::~IPCObjectStub() +{ + SendDeadNotification(); +} + +int IPCObjectStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + IPC_LOG("IPCObjectStub::OnRemoteRequest Called\n"); + return -1; +} + +void IPCObjectStub::CreateThread(key_t shmKey) +{ + IpcCenter::threadNum_++; + std::thread new_thread(std::bind(IpcCenter::ProcessHandle, shmKey, this)); + new_thread.detach(); + recvFd_ = IPCSkeleton::SocketListening(IPC_CLIENT_SOCKET_ADDR); + IPCSocketManager::InsertSocketFd(1, recvFd_); + if (recvFd_ < 0) { + IPC_LOG("Stub socket listen failed\n"); + } +} + +void IPCObjectStub::SendDeadNotification() +{ + IpcShmData *shmPtr = OpenShm(g_client_server_shmKey); + if (shmPtr == nullptr) { + IPC_LOG("Open server shm failed\n"); + return; + } + + // waiting previous ipc + IPC_LOG("WAITING FOR PREVIOUS IPC\n"); + while (shmPtr->needReply); + + shmPtr->deadNotice = true; + shmPtr->handle = handle_; + + shmPtr->needReply = true; + + shmdt((void *)shmPtr); +} + +} // namespace OHOS diff --git a/ipc_proxy_manager.cpp b/ipc_proxy_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..36f8295f99ed313de8820941070bae3c52c64093 --- /dev/null +++ b/ipc_proxy_manager.cpp @@ -0,0 +1,31 @@ +#include "ipc_proxy_manager.h" + +namespace OHOS { + +std::map< unsigned long long, sptr< IPCObjectProxy > > IPCProxyManager::proxyMap_; +std::mutex IPCProxyManager::mutex_; + +sptr< IPCObjectProxy > IPCProxyManager::FindOrNewProxy(unsigned long long handle) +{ + std::lock_guard< std::mutex > lock(mutex_); + auto it = proxyMap_.find(handle); + if (it == proxyMap_.end()) { + sptr< IPCObjectProxy > proxy(new IPCObjectProxy(handle)); + proxyMap_.emplace(handle, proxy); + IPC_LOG("INSERT PROXY with handle=%llx\n", handle); + return proxy; + } + return it->second; +} + +void IPCProxyManager::CleanProxy(unsigned long long handle) +{ + std::lock_guard< std::mutex > lock(mutex_); + auto it = proxyMap_.find(handle); + if (it != proxyMap_.end()) { + it->second->SendObituary(); + proxyMap_.erase(it); + } +} + +} // namespace OHOS \ No newline at end of file diff --git a/ipc_skeleton.cpp b/ipc_skeleton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5de9a665868eb74fd872fd8ecc0d38e82f48aafe --- /dev/null +++ b/ipc_skeleton.cpp @@ -0,0 +1,173 @@ +#include +#include +#include + +#include "ipc_base.h" +#include "iremote_object.h" +#include "ipc_skeleton.h" + +namespace OHOS { + +sptr< IRemoteObject > IPCSkeleton::obj_ = nullptr; +sptr< IRemoteObject > IPCSkeleton::deviceAuthObj_ = nullptr; + +pid_t IPCSkeleton::GetCallingPid() +{ + return getpid(); +} + +uid_t IPCSkeleton::GetCallingUid() +{ + return getuid(); +} + +bool IPCSkeleton::SetContextObject(sptr< IRemoteObject > &object) +{ + obj_ = object; + return true; +} + +sptr< IRemoteObject > IPCSkeleton::GetContextObject() +{ + if (obj_ == nullptr) { + obj_ = new IRemoteObject(); + } + return obj_; +} + +bool IPCSkeleton::SetDeviceAuthObj(sptr< IRemoteObject > obj) +{ + deviceAuthObj_ = obj; + return true; +} + +sptr< IRemoteObject > GetDeviceAuthObj() +{ + return deviceAuthObj_; +} + +int IPCSkeleton::SocketListening(const char *addr) +{ + unlink(addr); + + int socketFd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); + if (socketFd < 0) { + IPC_LOG("Socket failed errno=%d\n", errno); + return false; + } + + struct sockaddr_un socketAddr; + memset(&socketAddr, 0, sizeof(socketAddr)); + socketAddr.sun_family = AF_UNIX; + strcpy(socketAddr.sun_path, addr); + int ret = bind(socketFd, (struct sockaddr *)&socketAddr, sizeof(socketAddr)); + if (ret < 0) { + IPC_LOG("Bind socket failed errno=%d\n", errno); + close(socketFd); + socketFd = -1; + return false; + } + + ret = listen(socketFd, 3); + if (ret < 0) { + IPC_LOG("listen socket failed errno=%d\n", errno); + close(socketFd); + socketFd = -1; + return false; + } + return socketFd; +} + +int IPCSkeleton::SocketReadFd(int socketFd) +{ + if (socketFd < 0) { + IPC_LOG("Read fd from an uninitialized socket\n"); + return -1; + } + + struct sockaddr_un acceptAddr; + socklen_t sockLen = sizeof(acceptAddr); + int recvFd = accept(socketFd, (struct sockaddr *)&acceptAddr, &sockLen); + if (recvFd < 0) { + IPC_LOG("Accept failed errno=%d\n", errno); + return -1; + } + + struct msghdr msg; + struct iovec iov[1]; + char buf[100] = ""; + msg.msg_name = nullptr; + msg.msg_namelen = 0; + iov[0].iov_base = buf; + iov[0].iov_len = 100; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + char cm[CMSG_LEN(sizeof(int))]; + msg.msg_control = cm; + msg.msg_controllen = CMSG_LEN(sizeof(int)); + int ret = recvmsg(recvFd, &msg, 0); + if (ret < 0) { + IPC_LOG("Receive error, errno=%d\n", errno); + close(recvFd); + return -1; + } + + struct cmsghdr *cmsgPtr = CMSG_FIRSTHDR(&msg); + if (cmsgPtr == nullptr || cmsgPtr->cmsg_len != CMSG_LEN(sizeof(int)) || + cmsgPtr->cmsg_level != SOL_SOCKET || + cmsgPtr->cmsg_type != SCM_RIGHTS) { + IPC_LOG("Received wrong data\n"); + close(recvFd); + return -1; + } + close(recvFd); + return *((int *)CMSG_DATA(cmsgPtr)); +} + +bool IPCSkeleton::SocketWriteFd(const char *addr, int fd) +{ + int socketFd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); + if (socketFd < 0) { + IPC_LOG("Socket failed errno=%d\n", errno); + return false; + } + + struct sockaddr_un socketAddr; + memset(&socketAddr, 0, sizeof(socketAddr)); + socketAddr.sun_family = AF_UNIX; + strcpy(socketAddr.sun_path, addr); + int ret = connect(socketFd, (struct sockaddr *)&socketAddr, sizeof(socketAddr)); + if (ret < 0) { + IPC_LOG("Connect failed errno=%d\n", errno); + close(socketFd); + return false; + } + + struct msghdr msg; + struct iovec iov[1]; + char buf[100] = "IPC Socket Data with File Descriptor"; + msg.msg_name = nullptr; + msg.msg_namelen = 0; + iov[0].iov_base = buf; + iov[0].iov_len = 100; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + char cm[CMSG_LEN(sizeof(int))]; + msg.msg_control = cm; + msg.msg_controllen = CMSG_LEN(sizeof(int)); + struct cmsghdr *cmsgPtr = CMSG_FIRSTHDR(&msg); + cmsgPtr->cmsg_len = CMSG_LEN(sizeof(int)); + cmsgPtr->cmsg_level = SOL_SOCKET; + cmsgPtr->cmsg_type = SCM_RIGHTS; + *((int *)CMSG_DATA(cmsgPtr)) = fd; + ret = sendmsg(socketFd, &msg, 0); + if (ret < 0) { + IPC_LOG("Send failed errno=%d\n", errno); + } + close(socketFd); + return ret >= 0; +} + +} //namespace OHOS diff --git a/ipc_socket_manager.cpp b/ipc_socket_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08c463531672b3f435beffa810ee15aa0fd9538d --- /dev/null +++ b/ipc_socket_manager.cpp @@ -0,0 +1,24 @@ +#include "ipc_socket_manager.h" + +namespace OHOS { + +std::map< unsigned long long, int > IPCSocketManager::socketFdMap_; +std::mutex IPCSocketManager::mutex_; + +void IPCSocketManager::InsertSocketFd(unsigned long long handle, int socketFd) +{ + std::lock_guard< std::mutex > lock(mutex_); + socketFdMap_.emplace(handle, socketFd); +} + +int IPCSocketManager::FindSocketFd(unsigned long long handle) +{ + std::lock_guard< std::mutex > lock(mutex_); + auto it = socketFdMap_.find(handle); + if (it == socketFdMap_.end()) { + return -1; + } + return it->second; +} + +} // namespace OHOS \ No newline at end of file diff --git a/ipc_stub_manager.cpp b/ipc_stub_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ea2434d1a9e773d17a8e624d554ac75d1a91334 --- /dev/null +++ b/ipc_stub_manager.cpp @@ -0,0 +1,20 @@ +#include "ipc_stub_manager.h" + +namespace OHOS { + +std::map< unsigned long long, sptr< IPCObjectStub > > IPCStubManager::stubMap_; +std::mutex IPCStubManager::mutex_; + +unsigned long long IPCStubManager::GetHandleNum() +{ + std::lock_guard< std::mutex > lock(mutex_); + return stubMap_.size(); +} + +void IPCStubManager::InsertStub(unsigned long long handle, sptr< IPCObjectStub > stub) +{ + std::lock_guard< std::mutex > lock(mutex_); + stubMap_.emplace(handle, stub); +} + +} // namespace OHOS \ No newline at end of file diff --git a/iremote_object.cpp b/iremote_object.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9bee42a3b0f181d1f1c190060d2b50ce6698ffac --- /dev/null +++ b/iremote_object.cpp @@ -0,0 +1,103 @@ +#include "ipc_base.h" +#include "iremote_object.h" +#include "ipc_skeleton.h" +#include "ipc_socket_manager.h" + +key_t g_client_server_shmKey = 0x544F53; +key_t g_device_auth_shmKey = 0x52544F; + +namespace OHOS { + +static const char *IPC_SERVER_SOCKET_ADDR = "/tmp/ipc.socket.server"; + +IRemoteObject::IRemoteObject() : handle_(0), isDSoftBusObj(true) {} + +IRemoteObject::~IRemoteObject() {} + +bool IRemoteObject::AddDeathRecipient(const sptr< DeathRecipient > &recipient) +{ + return true; +} + +bool IRemoteObject::RemoveDeathRecipient(const sptr< DeathRecipient > &recipient) +{ + return true; +} + +int IRemoteObject::SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + IpcShmData *shmPtr = NULL; + + if (code == GET_SA_REQUEST_CODE || (code >= WIFI_DEVICE_ABILITY_ID && code <= WIFI_P2P_ABILITY_ID)) { + reply.isContainHandle_ = true; + reply.RemoteObjectHandle_ = 0; + return 0; + } + + shmPtr = OpenShm(isDSoftBusObj ? g_client_server_shmKey : g_device_auth_shmKey); + if (shmPtr == nullptr) { + IPC_LOG("Open server shm failed\n"); + return -1; + } + + IPC_DEBUG("WAITING FOR PREVIOUS IPC\n"); + + // waiting previous ipc + while (shmPtr->needReply); + + IPC_DEBUG("SENDING REQUEST with code=%u\n", code); + + shmPtr->requestCode = code; + shmPtr->inputSz = data.GetDataSize(); + if (shmPtr->inputSz > DATA_SIZE) { + IPC_LOG("Sending data overflow!"); + } + memcpy(shmPtr->inputData, (void *)data.GetData(), shmPtr->inputSz); + if (data.ContainFileDescriptors()) { + IPC_DEBUG("SENDING FD\n"); + shmPtr->containFd = true; + if (!IPCSkeleton::SocketWriteFd(IPC_SERVER_SOCKET_ADDR, data.ReadFileDescriptor())) { + IPC_LOG("Send File Descriptor failed\n"); + shmdt((void*)shmPtr); + return -1; + } + } + if (data.isContainHandle_) { + shmPtr->containHandle = true; + shmPtr->handle = data.RemoteObjectHandle_; + } + shmPtr->needReply = true; + + // waiting receiver reply + while (shmPtr->needReply); + IPC_DEBUG("RECEIVED DATA FROM REMOTE with code=%u\n", code); + + reply.WriteUnpadBuffer(shmPtr->outputData, shmPtr->outputSz); + if (shmPtr->containFd) { + if (!reply.WriteFileDescriptor(IPCSkeleton::SocketReadFd(IPCSocketManager::FindSocketFd(0)))) { + IPC_LOG("Receive reply fd failed"); + shmdt((void *)shmPtr); + return -1; + } + shmPtr->containFd = false; + } + if (shmPtr->containHandle) { + reply.isContainHandle_ = true; + reply.RemoteObjectHandle_ = shmPtr->handle; + shmPtr->containHandle = false; + } + shmdt((void *)shmPtr); + return 0; +} + +bool IRemoteObject::Marshalling(Parcel &parcel) const +{ + return true; +} + +unsigned long long IRemoteObject::GetHandle() +{ + return handle_; +} + +} // namespace OHOS diff --git a/message_parcel.cpp b/message_parcel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4329fc9252c393edf2bad5289d675130ed0a2c40 --- /dev/null +++ b/message_parcel.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include "ipc_base.h" +#include "message_parcel.h" +#include "ipc_skeleton.h" +#include "iremote_object.h" +#include "ipc_proxy_manager.h" +#include "ipc_stub_manager.h" + +namespace OHOS { + +MessageParcel::MessageParcel() : Parcel(), isContainHandle_(false), fd_(-1) {} + +MessageParcel::~MessageParcel() {} + +bool MessageParcel::WriteFileDescriptor(int fd) +{ + if (fd < 0) { + return false; + } + + int dupFd = dup(fd); + if (dupFd < 0) { + return false; + } + + fd_ = dupFd; + + return true; +} + +int MessageParcel::ReadFileDescriptor() +{ + return fd_; +} + +bool MessageParcel::ContainFileDescriptors() const +{ + return fd_ >= 0; +} + +bool MessageParcel::WriteRawData(const void *data, size_t size) +{ + if (data == nullptr || size > MAX_RAWDATA_SIZE) { + return false; + } + if (!WriteInt32(size)) { + return false; + } + + return WriteUnpadBuffer(data, size); +} + +const void *MessageParcel::ReadRawData(size_t size) +{ + int32_t bufferSize = ReadInt32(); + if (static_cast< unsigned int >(bufferSize) != size) { + return nullptr; + } + return ReadUnpadBuffer(size); +} + +bool MessageParcel::ContainRemoteObject() +{ + return isContainHandle_; +} + +sptr< IRemoteObject > MessageParcel::ReadRemoteObject() +{ + if (!isContainHandle_) { + IPC_LOG("Read an invalid remote object!\n"); + return nullptr; + } + if (!RemoteObjectHandle_) { + return IPCSkeleton::GetContextObject(); + } + return IPCProxyManager::FindOrNewProxy(RemoteObjectHandle_); +} + +bool MessageParcel::WriteRemoteObject(const sptr< IRemoteObject > &object) +{ + isContainHandle_ = true; + RemoteObjectHandle_ = object->GetHandle(); + return true; +} + +} //namespace OHOS