From 37d76f0b905a8a9f1ff46005e4cf1507714c7c23 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 16 Jun 2021 15:46:30 +0900 Subject: [PATCH] Add new functions for RPC-Port After this patch is applied, the rpc-port uses unix domain socket instead of socket pair. When the stub calls aul_rpc_port_create(), AMD creates the socket. And then, AMD sends the socket fd to the stub. The stub process uses the received socket fd for managing the connection. Adds: - aul_rpc_port_usr_prepare_stub() - aul_rpc_port_create() - aul_rpc_port_usr_create() - aul_rpc_port_destroy() - aul_rpc_port_usr_destroy() - aul_rpc_port_add_watch() - aul_rpc_port_usr_add_watch() - aul_rpc_port_remove_watch() - aul_rpc_port_exist() - aul_rpc_port_usr_exist() - aul_rpc_port_get_path() - aul_rpc_port_usr_get_path() Change-Id: I71a7bdaf7ba50e456c6662c524bf3d833030e4e6 Signed-off-by: Hwankyu Jhun --- include/aul_cmd.h | 4 + include/aul_rpc_port.h | 60 ++++++++++- src/aul_cmd.c | 4 + src/aul_rpc_port.cc | 272 ++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 324 insertions(+), 16 deletions(-) diff --git a/include/aul_cmd.h b/include/aul_cmd.h index 9ded442..305c4fe 100644 --- a/include/aul_cmd.h +++ b/include/aul_cmd.h @@ -205,6 +205,10 @@ enum app_cmd { PROC_DEREGISTER = 162, PROC_GET_NAME = 163, PROC_GET_EXTRA = 164, + RPC_PORT_CREATE = 165, + + RPC_PORT_DESTROY = 166, + RPC_PORT_EXIST = 167, APP_CMD_MAX }; diff --git a/include/aul_rpc_port.h b/include/aul_rpc_port.h index 1fc68f2..224857c 100644 --- a/include/aul_rpc_port.h +++ b/include/aul_rpc_port.h @@ -17,23 +17,75 @@ #ifndef __AUL_RPC_PORT_H__ #define __AUL_RPC_PORT_H__ +#include +#include + +#include + #ifdef __cplusplus extern "C" { #endif +#ifndef AUL_K_RPC_PORT #define AUL_K_RPC_PORT "__K_RPC_PORT" +#endif + +typedef void *aul_rpc_port_watch_h; + +typedef void (*aul_rpc_port_appeared_cb)(const char *app_id, + const char *port_name, int pid, void *user_data); -int aul_rpc_port_prepare_stub(const char *appid, const char *port_name); +typedef void (*aul_rpc_port_vanished_cb)(const char *app_id, + const char *port_name, int pid, void *user_data); -int aul_rpc_port_create_socket_pair(const char *appid, const char *port_name, +int aul_rpc_port_prepare_stub(const char *app_id, const char *port_name); + +int aul_rpc_port_usr_prepare_stub(const char *app_id, const char *port_name, + uid_t uid); + +int aul_rpc_port_create_socket_pair(const char *app_id, const char *port_name, int (*fds)[2]); int aul_rpc_port_notify_rpc_finished(void); -int aul_rpc_port_set_private_sharing(const char *appid, const char *paths[], +int aul_rpc_port_set_private_sharing(const char *app_id, const char *paths[], unsigned int size); -int aul_rpc_port_unset_private_sharing(const char *appid); +int aul_rpc_port_unset_private_sharing(const char *app_id); + +int aul_rpc_port_create(const char *port_name, int *fd); + +int aul_rpc_port_usr_create(const char *port_name, uid_t uid, int *fd); + +int aul_rpc_port_destroy(const char *port_name); + +int aul_rpc_port_usr_destroy(const char *port_name, uid_t uid); + +int aul_rpc_port_add_watch(const char *app_id, const char *port_name, + aul_rpc_port_appeared_cb appeared_cb, + aul_rpc_port_vanished_cb vanished_cb, + void *user_data, + aul_rpc_port_watch_h *handle); + +int aul_rpc_port_usr_add_watch(const char *app_id, const char *port_name, + aul_rpc_port_appeared_cb appeared_cb, + aul_rpc_port_vanished_cb vanished_cb, + void *user_data, uid_t uid, + aul_rpc_port_watch_h *handle); + + +int aul_rpc_port_remove_watch(aul_rpc_port_watch_h handle); + +int aul_rpc_port_exist(const char *appid, const char *port_name, bool *exist); + +int aul_rpc_port_usr_exist(const char *appid, const char *port_name, uid_t uid, + bool *exist); + +int aul_rpc_port_get_path(const char *appid, const char *port_name, + char **path); + +int aul_rpc_port_usr_get_path(const char *appid, const char *port_name, + uid_t uid, char **path); #ifdef __cplusplus } diff --git a/src/aul_cmd.c b/src/aul_cmd.c index 3c26ec4..2c9a1c2 100644 --- a/src/aul_cmd.c +++ b/src/aul_cmd.c @@ -207,6 +207,10 @@ API const char *aul_cmd_convert_to_string(int cmd) "PROC_DEREGISTER", "PROC_GET_NAME", "PROC_GET_EXTRA", + "RPC_PORT_CREATE", + + "RPC_PORT_DESTROY", + "RPC_PORT_EXIST", "CUSTOM_COMMAND" }; diff --git a/src/aul_rpc_port.cc b/src/aul_rpc_port.cc index 38e3edf..f418b11 100644 --- a/src/aul_rpc_port.cc +++ b/src/aul_rpc_port.cc @@ -16,14 +16,19 @@ #include #include +#include #include #include #include +#include +#include + #include "app_request.h" #include "aul_api.h" #include "aul_util.h" #include "include/aul.h" +#include "include/aul_app_com.h" #include "include/aul_error.h" #include "include/aul_rpc_port.h" #include "include/aul_sock.h" @@ -31,17 +36,114 @@ using namespace aul::internal; +namespace { + +constexpr const char kEndpoint[] = "org.tizen.rpcport"; +constexpr const char kInterfacePrefix[] = "org.tizen.rpcport._"; +constexpr const char kPathRunAulRpcPort[] = "/run/aul/rpcport/"; + +class WatchInfo { + public: + WatchInfo(std::string app_id, std::string port_name, + aul_rpc_port_appeared_cb appeared_cb, + aul_rpc_port_vanished_cb vanished_cb, + void* user_data, uid_t uid) + : app_id_(std::move(app_id)), + port_name_(std::move(port_name)), + appeared_cb_(appeared_cb), + vanished_cb_(vanished_cb), + user_data_(user_data), + uid_(uid) { + } + + ~WatchInfo() {} + + int Watch() { + int ret = aul_app_com_create(kEndpoint, nullptr, AppComCb, this, &conn_); + if (ret != AUL_R_OK) + _E("aul_app_com_create() is failed. error(%d)", ret); + + return ret; + } + + void Unwatch() { + if (conn_) { + aul_app_com_leave(conn_); + conn_ = nullptr; + } + } + + private: + static int AppComCb(const char* endpoint, aul_app_com_result_e result, + bundle* envelope, void* user_data) { + auto* info = static_cast(user_data); + tizen_base::Bundle b(envelope, false, false); + std::string app_id = b.GetString(AUL_K_APPID); + if (info->app_id_ != app_id) + return -1; + + std::string port_name = b.GetString(AUL_K_RPC_PORT); + if (info->port_name_ != port_name) + return -1; + + std::string uid_str = b.GetString(AUL_K_CALLER_UID); + uid_t uid = std::stoul(uid_str, nullptr, 10); + if (info->uid_ != uid) + return -1; + + std::string pid_str = b.GetString(AUL_K_PID); + int pid = std::stoi(pid_str); + std::string event_name = b.GetString(AUL_K_EVENT_NAME); + if (event_name == "Appeared") { + info->appeared_cb_(app_id.c_str(), port_name.c_str(), pid, + info->user_data_); + } else { + info->vanished_cb_(app_id.c_str(), port_name.c_str(), pid, + info->user_data_); + } + + return 0; + } + + private: + std::string app_id_; + std::string port_name_; + aul_rpc_port_appeared_cb appeared_cb_; + aul_rpc_port_vanished_cb vanished_cb_; + void* user_data_; + uid_t uid_; + aul_app_com_connection_h conn_ = nullptr; +}; + +std::string GetInterfaceName(const std::string& app_id, + const std::string& port_name, uid_t uid) { + std::string name = kInterfacePrefix + app_id + "_" + port_name; + char* checksum = g_compute_checksum_for_string(G_CHECKSUM_SHA1, + name.c_str(), name.length()); + std::unique_ptr checksum_auto(checksum, g_free); + return std::to_string(uid) + "@" + std::string(checksum); +} + +std::string GetPath(const std::string& interface_name) { + return std::string(kPathRunAulRpcPort) + "/." + interface_name; +} + +} // namespace + extern "C" API int aul_rpc_port_prepare_stub(const char* app_id, const char* port_name) { + return aul_rpc_port_usr_prepare_stub(app_id, port_name, getuid()); +} + +extern "C" API int aul_rpc_port_usr_prepare_stub(const char* app_id, + const char* port_name, uid_t uid) { if (app_id == nullptr || port_name == nullptr) { _E("Invalid parameter"); return AUL_R_EINVAL; } - tizen_base::Bundle b; - b.Add(AUL_K_RPC_PORT, port_name); - - int ret = AppRequest(RPC_PORT_PREPARE_STUB, getuid()) + tizen_base::Bundle b {{AUL_K_RPC_PORT, port_name}}; + int ret = AppRequest(RPC_PORT_PREPARE_STUB, uid) .With(b) .SetAppId(app_id) .SendSimply(); @@ -60,9 +162,7 @@ extern "C" API int aul_rpc_port_create_socket_pair(const char* app_id, return AUL_R_EINVAL; } - tizen_base::Bundle b; - b.Add(AUL_K_RPC_PORT, port_name); - + tizen_base::Bundle b {{AUL_K_RPC_PORT, port_name}}; int fd = AppRequest(RPC_PORT_CREATE_SOCKET_PAIR, getuid()) .With(b) .SetAppId(app_id) @@ -100,8 +200,7 @@ extern "C" API int aul_rpc_port_set_private_sharing(const char* app_id, return AUL_R_EINVAL; } - tizen_base::Bundle b; - b.Add(AUL_K_CALLEE_APPID, app_id); + tizen_base::Bundle b {{AUL_K_CALLEE_APPID, app_id}}; std::vector v; for (unsigned int i = 0; i < size; ++i) v.push_back(paths[i]); @@ -125,9 +224,7 @@ extern "C" API int aul_rpc_port_unset_private_sharing(const char* app_id) { return AUL_R_EINVAL; } - tizen_base::Bundle b; - b.Add(AUL_K_CALLEE_APPID, app_id); - + tizen_base::Bundle b {{AUL_K_CALLEE_APPID, app_id}}; int ret = AppRequest(UNSET_PRIVATE_SHARING, getuid()) .With(b) .SetPid(getpid()) @@ -139,3 +236,154 @@ extern "C" API int aul_rpc_port_unset_private_sharing(const char* app_id) { return AUL_R_OK; } + +extern "C" API int aul_rpc_port_create(const char* port_name, int* fd) { + return aul_rpc_port_usr_create(port_name, getuid(), fd); +} + +extern "C" API int aul_rpc_port_usr_create(const char* port_name, uid_t uid, + int* fd) { + if (port_name == nullptr || fd == nullptr) { + _E("Invalid paramter"); + return AUL_R_EINVAL; + } + + tizen_base::Bundle b {{AUL_K_RPC_PORT, port_name}}; + int req_fd = AppRequest(RPC_PORT_CREATE, uid) + .With(b) + .SendSimply(AUL_SOCK_ASYNC); + if (req_fd <= 0 || req_fd > sysconf(_SC_OPEN_MAX)) { + _E("Failed to send socket creation request. error(%d)", req_fd); + return req_fd; + } + + int fds[2] = { -1, }; + int ret = aul_sock_recv_reply_sock_fd(req_fd, &fds, 1); + if (ret != 0) { + _E("Failed to receive socket fds. error(%d)", ret); + return aul_error_convert(ret); + } + + *fd = fds[0]; + return AUL_R_OK; +} + +extern "C" API int aul_rpc_port_destroy(const char* port_name) { + return aul_rpc_port_usr_destroy(port_name, getuid()); +} + +extern "C" API int aul_rpc_port_usr_destroy(const char* port_name, uid_t uid) { + if (port_name == nullptr) { + _E("Invalid parameter"); + return AUL_R_EINVAL; + } + + tizen_base::Bundle b {{AUL_K_RPC_PORT, port_name}}; + int ret = AppRequest(RPC_PORT_DESTROY, uid) + .With(b) + .SendSimply(AUL_SOCK_NOREPLY); + if (ret != 0) { + _E("Failed to send socket desctruction request. error(%d)", ret); + return ret; + } + + return AUL_R_OK; +} + +extern "C" API int aul_rpc_port_add_watch(const char* app_id, + const char* port_name, aul_rpc_port_appeared_cb appeared_cb, + aul_rpc_port_vanished_cb vanished_cb, void* user_data, + aul_rpc_port_watch_h* handle) { + return aul_rpc_port_usr_add_watch(app_id, port_name, appeared_cb, vanished_cb, + user_data, getuid(), handle); +} + +extern "C" API int aul_rpc_port_usr_add_watch(const char* app_id, + const char* port_name, aul_rpc_port_appeared_cb appeared_cb, + aul_rpc_port_vanished_cb vanished_cb, void* user_data, uid_t uid, + aul_rpc_port_watch_h* handle) { + if (app_id == nullptr || port_name == nullptr || appeared_cb == nullptr || + vanished_cb == nullptr || handle == nullptr) { + _E("Invalid parameter"); + return AUL_R_EINVAL; + } + + auto* info = new (std::nothrow) WatchInfo(app_id, port_name, appeared_cb, + vanished_cb, user_data, uid); + if (info == nullptr) { + _E("Out of memory"); + return AUL_R_ENOMEM; + } + + int ret = info->Watch(); + if (ret != AUL_R_OK) { + delete info; + return ret; + } + + *handle = static_cast(info); + return AUL_R_OK; +} + +extern "C" API int aul_rpc_port_remove_watch(aul_rpc_port_watch_h handle) { + if (handle == nullptr) { + _E("Invalid parameter"); + return AUL_R_EINVAL; + } + + auto* info = static_cast(handle); + info->Unwatch(); + delete info; + return AUL_R_OK; +} + +extern "C" API int aul_rpc_port_exist(const char* app_id, const char* port_name, + bool* exist) { + return aul_rpc_port_usr_exist(app_id, port_name, getuid(), exist); +} + +extern "C" API int aul_rpc_port_usr_exist(const char* app_id, + const char* port_name, uid_t uid, bool* exist) { + if (app_id == nullptr || port_name == nullptr || exist == nullptr) { + _E("Invalid parameter"); + return AUL_R_EINVAL; + } + + tizen_base::Bundle b {{AUL_K_RPC_PORT, port_name}}; + int ret = AppRequest(RPC_PORT_EXIST, uid) + .With(b) + .SetAppId(app_id) + .SendSimply(); + if (ret < 0) { + _E("Failed to send request. error(%d)", ret); + return ret; + } + + *exist = (ret == 1) ? true : false; + return AUL_R_OK; +} + +extern "C" API int aul_rpc_port_get_path(const char* app_id, + const char* port_name, char** path) { + return aul_rpc_port_usr_get_path(app_id, port_name, getuid(), path); +} + +extern "C" API int aul_rpc_port_usr_get_path(const char* app_id, + const char* port_name, uid_t uid, char** path) { + if (app_id == nullptr || port_name == nullptr || path == nullptr) { + _E("Invalid parameter"); + return AUL_R_EINVAL; + } + + std::string interface_name = GetInterfaceName(app_id, port_name, uid); + std::string port_path = GetPath(interface_name); + struct sockaddr_un addr = { 0, }; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", port_path.c_str()); + *path = strdup(addr.sun_path); + if (*path == nullptr) { + _E("Out of memory"); + return AUL_R_ENOMEM; + } + + return AUL_R_OK; +} -- 2.7.4