diff --git a/include/ipc_base.h b/include/ipc_base.h index d289e5105c739319df9a0eb5b41fa3b5b74d1e00..9be46546731a610cf425b7a96e8b397eda924245 100644 --- a/include/ipc_base.h +++ b/include/ipc_base.h @@ -5,19 +5,25 @@ #include #include #include -#include -#include +#include +#include #define IPC_LOG(fmt, args...) \ - printf("[IPC LOG %s:%u]" fmt, __FILE__, __LINE__, ##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_send_shm_key; -extern key_t g_receive_shm_key; +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; @@ -26,13 +32,17 @@ struct IpcShmData { 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\n"); + IPC_LOG("Get shm failed, errno=%d\n", errno); return nullptr; } void *shmPtr = shmat(shmFd, 0, 0); @@ -53,4 +63,16 @@ 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 index ebf9891cd62d2e0f3b0e795e5dcc2a994aa2d1df..999bf54edad8931a391195168b9cbe3befa650e2 100644 --- a/include/ipc_center.h +++ b/include/ipc_center.h @@ -8,15 +8,11 @@ namespace OHOS { class IpcCenter { public: - IpcCenter(); - bool Init(bool isServer, IPCObjectStub *stub); - bool ThreadCreate(); - void ProcessHandle(); -private: - bool ShmInit(key_t ShmKey); - size_t threadNum_; - IPCObjectStub *ipcStub_; - bool needStop_; + 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 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 index ec93b6d75fba5d09dfd3563f04067746ecfde715..a1306ab176081a334f22740879c6db92db9d67cb 100644 --- a/include/ipc_object_stub.h +++ b/include/ipc_object_stub.h @@ -1,6 +1,8 @@ #ifndef _IPC_OBJECT_STUB_H_ #define _IPC_OBJECT_STUB_H_ +#include + #include "iremote_object.h" namespace OHOS { @@ -10,6 +12,11 @@ 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 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 index 45260cbf93c68c97de3732a8483bf3ef57516fb4..310624364cc18118e2aab8d17a3d26ace0797128 100644 --- a/include/ipc_skeleton.h +++ b/include/ipc_skeleton.h @@ -19,14 +19,15 @@ public: static uid_t GetCallingUid(); static sptr< IRemoteObject > GetContextObject(); static bool SetContextObject(sptr< IRemoteObject > &object); - static bool SocketListening(bool isServer); - static int SocketReadFd(); - static bool SocketWriteFd(int fd); + 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 int socketFd_; - static bool isServer_; + static sptr< IRemoteObject > deviceAuthObj_; }; } // namespace OHOS 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/iremote_broker.h b/include/iremote_broker.h index e6f54250493c6bdff1959ac235d193eec3139062..6d88e11a413a671a4a54f23093989685a632c1bc 100644 --- a/include/iremote_broker.h +++ b/include/iremote_broker.h @@ -2,12 +2,102 @@ #define _IREMOTE_BROKER_H #ifdef __cplusplus +#include +#include +#include +#include "iremote_object.h" +#include "refbase.h" namespace OHOS { -template class BrokerDelegator { +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_; \ + } + +template class BrokerCreator { +public: + BrokerCreator() = default; + ~BrokerCreator() = default; + sptr operator () (const sptr &object) + { + T *proxy = new (std::nothrow) T(object); + if (proxy != nullptr) { + return static_cast(proxy); + } + return nullptr; + }; +}; + +class BrokerRegistration { + using Constructor = std::function(const sptr &object)>; + +public: + static BrokerRegistration &Get(); + bool Register(const std::u16string &descriptor, const Constructor &creator); + void Unregister(const std::u16string &descriptor); + sptr NewInstance(const std::u16string &descriptor, const sptr &object); + +protected: + BrokerRegistration() = default; + ~BrokerRegistration(); + +private: + BrokerRegistration(const BrokerRegistration &) = delete; + BrokerRegistration(BrokerRegistration &&) = delete; + BrokerRegistration &operator = (const BrokerRegistration &) = delete; + BrokerRegistration &operator = (BrokerRegistration &&) = delete; + std::mutex creatorMutex_; + std::unordered_map creators_; +}; + +template class BrokerDelegator { +public: + BrokerDelegator(); + ~BrokerDelegator(); + +private: + BrokerDelegator(const BrokerDelegator &) = delete; + BrokerDelegator(BrokerDelegator &&) = delete; + BrokerDelegator &operator = (const BrokerDelegator &) = delete; + BrokerDelegator &operator = (BrokerDelegator &&) = delete; +}; + +template BrokerDelegator::BrokerDelegator() +{ + const std::u16string descriptor = T::GetDescriptor(); + BrokerRegistration ®istration = BrokerRegistration::Get(); + registration.Register(descriptor, BrokerCreator()); +} + +template BrokerDelegator::~BrokerDelegator() +{ + const std::u16string descriptor = T::GetDescriptor(); + BrokerRegistration ®istration = BrokerRegistration::Get(); + registration.Unregister(descriptor); +} + +template inline sptr iface_cast(const sptr &object) +{ + const std::u16string descriptor = INTERFACE::GetDescriptor(); + BrokerRegistration ®istration = BrokerRegistration::Get(); + sptr broker = registration.NewInstance(descriptor, object); + return static_cast(broker.GetRefPtr()); +} + }; #endif diff --git a/include/iremote_object.h b/include/iremote_object.h index a955172eb1b429ddf2bf73dec46ebbaf0f3d9569..dc422e070be7dde39b13e6a580502ee5a832c9e0 100644 --- a/include/iremote_object.h +++ b/include/iremote_object.h @@ -3,29 +3,19 @@ #include "message_parcel.h" #include "message_option.h" +#include "iremote_broker.h" -namespace OHOS { +#define ERR_NONE 0 +#define NO_ERROR 0 -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; - } -}; +namespace OHOS { -#define DECLARE_INTERFACE_DESCRIPTOR(DESCRIPTOR) \ - static inline const std::u16string metaDescriptor_ = {DESCRIPTOR} ; \ - static inline const std::u16string &GetDescriptor() \ - { \ - return metaDescriptor_; \ - } +class IRemoteBroker; class IRemoteObject : public virtual Parcelable { public: + IRemoteObject(); + ~IRemoteObject(); class DeathRecipient : public RefBase { public: virtual void OnRemoteDied(const wptr< IRemoteObject > &object) {} @@ -35,6 +25,11 @@ public: virtual bool AddDeathRecipient(const sptr< DeathRecipient > &recipient); virtual bool RemoveDeathRecipient(const sptr< DeathRecipient > &recipient); virtual bool Marshalling(Parcel &parcel) const override; + virtual bool IsProxyObject() const; + virtual sptr< IRemoteBroker > AsInterface(); + unsigned long long GetHandle(); + unsigned long long handle_; + bool isDSoftBusObj; }; } // namespace OHOS diff --git a/include/message_parcel.h b/include/message_parcel.h index e3ed991b3eaf28d59980c6b4501c28dc077f16b6..91f93e1b1ae3404fbaa6b9c93361a025121a73be 100644 --- a/include/message_parcel.h +++ b/include/message_parcel.h @@ -22,6 +22,9 @@ public: bool WriteInterfaceToken(std::u16string name); std::u16string ReadInterfaceToken(); size_t GetRawDataSize() const; + bool ContainRemoteObject(); + unsigned long long RemoteObjectHandle_; + bool isContainHandle_; private: static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M int fd_; diff --git a/ipc_center.cpp b/ipc_center.cpp index b51f39d15d8ef02d6915b50f360b345edb3ad85c..1c33e6b8325268743b6b75f49eaf50100e04def8 100644 --- a/ipc_center.cpp +++ b/ipc_center.cpp @@ -4,10 +4,15 @@ #include "ipc_base.h" #include "ipc_center.h" #include "ipc_skeleton.h" +#include "ipc_socket_manager.h" +#include "ipc_proxy_manager.h" namespace OHOS { -IpcCenter::IpcCenter() : threadNum_(0), needStop_(false) {} +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) { @@ -18,82 +23,130 @@ bool IpcCenter::ShmInit(key_t shmKey) } 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_send_shm_key) || !ShmInit(g_receive_shm_key))) { - IPC_LOG("Shm inti failed\n"); + if (isServer && !ShmInit(g_client_server_shmKey)) { + IPC_LOG("Shm init failed\n"); return false; } - if (isServer) { - std::swap(g_send_shm_key, g_receive_shm_key); + if (isServer && !ShmInit(g_device_auth_shmKey)) { + IPC_LOG("Device auth shm init failed\n"); + return false; } - ipcStub_ = stub; + if (stub->recvFd_ >= 0) { + close(stub->recvFd_); + } - if (!IPCSkeleton::SocketListening(isServer)) { + stub->recvFd_ = IPCSkeleton::SocketListening(IPC_SERVER_SOCKET_ADDR); + if (stub->recvFd_ < 0) { IPC_LOG("Starting socket listen failed\n"); return false; } - return ThreadCreate(); + IPCSocketManager::InsertSocketFd(0, stub->recvFd_); + stub->sendAddr_ = IPC_CLIENT_SOCKET_ADDR; + stub->handle_ = 0; + + return ThreadCreate(stub); } -void IpcCenter::ProcessHandle() +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 { - IpcShmData *shmPtr = OpenShm(g_receive_shm_key); - if (shmPtr == nullptr) { - return; - } 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())) { - IPC_LOG("Process file descriptor failed"); + if (!data.WriteFileDescriptor(IPCSkeleton::SocketReadFd(ipcStub->recvFd_))) { + IPC_LOG("Process file descriptor failed\n"); shmdt((void *)shmPtr); return; } } - ipcStub_->OnRemoteRequest(shmPtr->requestCode, data, reply, option); + 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(reply.ReadFileDescriptor())) { - IPC_LOG("Send file descriptor in reply failed\n") + 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; - shmdt((void*)shmPtr); - } while (!needStop_); + 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() +bool IpcCenter::ThreadCreate(IPCObjectStub *stub) { - if (!threadNum_) { - ++threadNum_; - std::thread new_thread(std::bind(&IpcCenter::ProcessHandle, this)); - new_thread.detach(); - return true; - } - return false; + ++threadNum_; + std::thread new_thread(std::bind(&IpcCenter::ProcessHandle, + stub->isDSoftBusObj ? g_client_server_shmKey : g_device_auth_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 index 7cae93f1cd3b11c4fbcbb7983afef2529007ccf6..4f7498309d859c0c957b0b043022706756c926fa 100644 --- a/ipc_object_stub.cpp +++ b/ipc_object_stub.cpp @@ -1,11 +1,32 @@ +#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 { -IPCObjectStub::IPCObjectStub() {} +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() {} +IPCObjectStub::~IPCObjectStub() +{ + SendDeadNotification(); +} int IPCObjectStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { @@ -13,4 +34,36 @@ int IPCObjectStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessagePa 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 index 9f70d36d0c279b9b423dcbd96dee713d5a02e196..7259cf94a21e16ca6a7e88389e6ca50a7c7c6996 100644 --- a/ipc_skeleton.cpp +++ b/ipc_skeleton.cpp @@ -8,12 +8,8 @@ namespace OHOS { -const char *IPC_SERVER_SOCKET_ADDR = "/tmp/ipc.socket.server"; -const char *IPC_CLIENT_SOCKET_ADDR = "/tmp/ipc.socket.client"; - sptr< IRemoteObject > IPCSkeleton::obj_ = nullptr; -int IPCSkeleton::socketFd_ = -1; -bool IPCSkeleton::isServer_ = true; +sptr< IRemoteObject > IPCSkeleton::deviceAuthObj_ = nullptr; pid_t IPCSkeleton::GetCallingPid() { @@ -39,20 +35,28 @@ sptr< IRemoteObject > IPCSkeleton::GetContextObject() return obj_; } -bool IPCSkeleton::SocketListening(bool isServer) +bool IPCSkeleton::SetDeviceAuthObj(sptr< IRemoteObject > obj) { - if (socketFd_ >= 0) { - IPC_LOG("Socket is opened\n"); - return false; - } + deviceAuthObj_ = obj; + deviceAuthObj_->isDSoftBusObj = false; + return true; +} - isServer_ = isServer; +sptr< IRemoteObject > IPCSkeleton::GetDeviceAuthObj() +{ + if (deviceAuthObj_ == nullptr) { + deviceAuthObj_ = new IRemoteObject(); + deviceAuthObj_->isDSoftBusObj = false; + } + return deviceAuthObj_; +} - const char *ipcPath = isServer ? IPC_SERVER_SOCKET_ADDR : IPC_CLIENT_SOCKET_ADDR; - unlink(ipcPath); +int IPCSkeleton::SocketListening(const char *addr) +{ + unlink(addr); - socketFd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); - if (socketFd_ < 0) { + int socketFd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); + if (socketFd < 0) { IPC_LOG("Socket failed errno=%d\n", errno); return false; } @@ -60,35 +64,35 @@ bool IPCSkeleton::SocketListening(bool isServer) struct sockaddr_un socketAddr; memset(&socketAddr, 0, sizeof(socketAddr)); socketAddr.sun_family = AF_UNIX; - strcpy(socketAddr.sun_path, ipcPath); - int ret = bind(socketFd_, (struct sockaddr *)&socketAddr, sizeof(socketAddr)); + 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; + close(socketFd); + socketFd = -1; return false; } - ret = listen(socketFd_, 3); + ret = listen(socketFd, 3); if (ret < 0) { IPC_LOG("listen socket failed errno=%d\n", errno); - close(socketFd_); - socketFd_ = -1; + close(socketFd); + socketFd = -1; return false; } - return true; + return socketFd; } -int IPCSkeleton::SocketReadFd() +int IPCSkeleton::SocketReadFd(int socketFd) { - if (socketFd_ < 0) { + 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); + int recvFd = accept(socketFd, (struct sockaddr *)&acceptAddr, &sockLen); if (recvFd < 0) { IPC_LOG("Accept failed errno=%d\n", errno); return -1; @@ -126,7 +130,7 @@ int IPCSkeleton::SocketReadFd() return *((int *)CMSG_DATA(cmsgPtr)); } -bool IPCSkeleton::SocketWriteFd(int fd) +bool IPCSkeleton::SocketWriteFd(const char *addr, int fd) { int socketFd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); if (socketFd < 0) { @@ -137,7 +141,7 @@ bool IPCSkeleton::SocketWriteFd(int fd) struct sockaddr_un socketAddr; memset(&socketAddr, 0, sizeof(socketAddr)); socketAddr.sun_family = AF_UNIX; - strcpy(socketAddr.sun_path, isServer_ ? IPC_CLIENT_SOCKET_ADDR : IPC_SERVER_SOCKET_ADDR); + 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); 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_broker.cpp b/iremote_broker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b932228c2d6a7d9fee048a44adead3d8216d0bec --- /dev/null +++ b/iremote_broker.cpp @@ -0,0 +1,61 @@ +#include "iremote_broker.h" +#include + +namespace OHOS { +BrokerRegistration &BrokerRegistration::Get() +{ + static BrokerRegistration instance; + return instance; +} + +BrokerRegistration::~BrokerRegistration() +{ + std::lock_guard lockGuard(creatorMutex_); + for (auto it = creators_.begin(); it != creators_.end();) { + it = creators_.erase(it); + } +} + +bool BrokerRegistration::Register(const std::u16string &descriptor, const Constructor &creator) +{ + if (descriptor.empty()) { + return false; + } + + std::lock_guard lockGuard(creatorMutex_); + auto it = creators_.find(descriptor); + if (it == creators_.end()) { + return creators_.insert({ descriptor, creator }).second; + } + return false; +} + +void BrokerRegistration::Unregister(const std::u16string &descriptor) +{ + std::lock_guard lockGuard(creatorMutex_); + if (!descriptor.empty()) { + auto it = creators_.find(descriptor); + if (it != creators_.end()) { + creators_.erase(it); + } + } +} + +sptr BrokerRegistration::NewInstance(const std::u16string &descriptor, const sptr &object) +{ + std::lock_guard lockGuard(creatorMutex_); + + sptr broker; + if (object != nullptr) { + if (object->IsProxyObject()) { + auto it = creators_.find(descriptor); + if (it != creators_.end()) { + broker = it->second(object); + } + } else { + broker = object->AsInterface().GetRefPtr(); + } + } + return broker; +} +} // namespace OHOS diff --git a/iremote_object.cpp b/iremote_object.cpp index 055258d7f5a26bbc6d326ac29043c7ee1be55bea..e2be1334849173d4659f99f5059c71742e74808d 100644 --- a/iremote_object.cpp +++ b/iremote_object.cpp @@ -1,13 +1,18 @@ #include "ipc_base.h" #include "iremote_object.h" #include "ipc_skeleton.h" +#include "ipc_socket_manager.h" -key_t g_send_shm_key = 0x544F53; -key_t g_receive_shm_key = 0x52544F; +key_t g_client_server_shmKey = 0x544F53; +key_t g_device_auth_shmKey = 0x52544F; namespace OHOS { -const int32_t GET_SA_REQUEST_CODE = 2; +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) { @@ -23,41 +28,64 @@ int IRemoteObject::SendRequest(uint32_t code, MessageParcel &data, MessageParcel { IpcShmData *shmPtr = NULL; - if (code == GET_SA_REQUEST_CODE) { + 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(g_send_shm_key); + 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(data.ReadFileDescriptor())) { + 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())) { - IPC_LOG("Reveive reply fd failed"); + 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; } @@ -67,4 +95,19 @@ bool IRemoteObject::Marshalling(Parcel &parcel) const return true; } +unsigned long long IRemoteObject::GetHandle() +{ + return handle_; +} + +sptr< IRemoteBroker > IRemoteObject::Asnterface() +{ + return nullptr; +} + +bool IRemoteObject::IsProxyObject() const +{ + return true; +} + } // namespace OHOS diff --git a/message_parcel.cpp b/message_parcel.cpp index 0dba88e0c46e20c46f41f791355902deae046b7f..a1e0a8124fdee88f351b29a571ab2b34969b09f9 100644 --- a/message_parcel.cpp +++ b/message_parcel.cpp @@ -6,10 +6,12 @@ #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(), fd_(-1) {} +MessageParcel::MessageParcel() : Parcel(), isContainHandle_(false), fd_(-1) {} MessageParcel::~MessageParcel() {} @@ -61,13 +63,27 @@ const void *MessageParcel::ReadRawData(size_t size) return ReadUnpadBuffer(size); } +bool MessageParcel::ContainRemoteObject() +{ + return isContainHandle_; +} + sptr< IRemoteObject > MessageParcel::ReadRemoteObject() { - return IPCSkeleton::GetContextObject(); + 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; }