From 7c768205c18aa3fa8900c84f4cbb8e8470dc1102 Mon Sep 17 00:00:00 2001 From: hyunho Date: Thu, 5 Nov 2020 18:49:22 +0900 Subject: Replace gdbus with socket for bulk communication Change-Id: I485ae58573534f63bf2c0cd5f4196792474756c8 Signed-off-by: hyunho --- notification-ex/CMakeLists.txt | 2 + notification-ex/dbus_event_listener.cc | 208 +++++++++++++-------- .../dbus_event_listener_implementation.h | 15 +- notification-ex/dbus_sender.cc | 199 ++++++++++++++------ notification-ex/dbus_sender.h | 6 +- notification-ex/dbus_sender_implementation.h | 7 +- notification-ex/event_sender_interface.h | 2 +- notification-ex/ex_util.cc | 117 +++++++++++- notification-ex/ex_util.h | 8 + notification-ex/manager.cc | 51 +++-- notification-ex/reporter.cc | 42 ++--- notification-ex/socket_handler.h | 41 ++++ notification-ex/stub.cc | 35 +++- 13 files changed, 541 insertions(+), 192 deletions(-) create mode 100644 notification-ex/socket_handler.h (limited to 'notification-ex') diff --git a/notification-ex/CMakeLists.txt b/notification-ex/CMakeLists.txt index 6464cf4..8c37ef6 100644 --- a/notification-ex/CMakeLists.txt +++ b/notification-ex/CMakeLists.txt @@ -12,6 +12,8 @@ SET(VERSION "${VERSION_MAJOR}.0.0") INCLUDE(FindPkgConfig) pkg_check_modules(notification-ex REQUIRED glib-2.0 + gio-2.0 + gio-unix-2.0 bundle dlog capi-appfw-app-control diff --git a/notification-ex/dbus_event_listener.cc b/notification-ex/dbus_event_listener.cc index e37a3a2..954a634 100644 --- a/notification-ex/dbus_event_listener.cc +++ b/notification-ex/dbus_event_listener.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,7 @@ #include "notification-ex/exception.h" #include "notification-ex/ex_util.h" #include "notification-ex/event_info_internal.h" +#include "notification-ex/socket_handler.h" #ifdef LOG_TAG #undef LOG_TAG @@ -168,7 +170,8 @@ void DBusEventListener::Impl::SignalCb(GDBusConnection* connection, const gchar* signal_name, GVariant* parameters, void* user_data) { - DBusEventListener::Impl* dl = static_cast(user_data); + DBusEventListener::Impl* dl = + static_cast(user_data); char* appid = nullptr; GVariantIter *iter = nullptr; char* event_info_raw = nullptr; @@ -216,51 +219,137 @@ void DBusEventListener::Impl::SignalCb(GDBusConnection* connection, } } -void DBusEventListener::Impl::MethodCallHandler(GVariant* parameters, - DBusEventListener::Impl* dl, pid_t pid, uid_t uid) { - char* appid = nullptr; - GVariantIter* iter = nullptr; - char* event_info_raw = nullptr; +int DBusEventListener::Impl::GetRecvSocket(GDBusMethodInvocation* invocation) { + GDBusMessage* msg = g_dbus_method_invocation_get_message(invocation); + GUnixFDList* fd_list = g_dbus_message_get_unix_fd_list(msg); + if (fd_list == NULL) { + LOGE("fd list is null"); + return -1; + } - g_variant_get(parameters, "(&s&sa(s))", &appid, &event_info_raw, &iter); + GError* g_err = nullptr; + int ret_fd = g_unix_fd_list_get(fd_list, 0, &g_err); + if (ret_fd == -1 || g_err) { + LOGE("g_unix_fd_list_get [%s]", g_err->message); + g_error_free(g_err); + return -1; + } - string sender_appid = string(appid); - string cur_appid = util::GetAppId(); - LOGI("MethodCallHandler!! appid(%s), sender(%s), cur(%s)", appid, - sender_appid.c_str(), cur_appid.c_str()); + LOGI("sender fd : %d", ret_fd); + return ret_fd; +} - if (sender_appid == cur_appid) { - g_variant_iter_free(iter); - return; +list DBusEventListener::Impl::ReadNotiList( + GDBusMethodInvocation* invocation, int noti_cnt) { + list ret_list; + list empty_list; + int recvfd = GetRecvSocket(invocation); + if (recvfd < 1) { + LOGE("Fail to get socket fd"); + return ret_list; } + ret_list = util::ReadBundleList(recvfd, noti_cnt); + return ret_list; +} + +int DBusEventListener::Impl::MethodCallHandler( + string sender_appid, string event_info_raw, int noti_cnt, + GDBusMethodInvocation* invocation, DBusEventListener::Impl* dl, + pid_t pid, uid_t uid) { + string cur_appid = util::GetAppId(); + LOGI("MethodCallHandler!! sender(%s), cur(%s)", + sender_appid.c_str(), cur_appid.c_str()); + + if (sender_appid == cur_appid) + return 0; if ((!DBusConnectionManager::GetInst().IsDataProviderMaster(cur_appid) && !DBusConnectionManager::GetInst().IsDataProviderMaster(sender_appid)) - || (cur_appid == sender_appid)) { - g_variant_iter_free(iter); - return; - } + || (cur_appid == sender_appid)) + return 0; - char* raw = nullptr; list ret_list; - while (g_variant_iter_loop(iter, "(&s)", &raw) && raw != nullptr) { - Bundle ret(raw); - ret_list.emplace_back(ret); + if (noti_cnt > 0) { + ret_list = dl->ReadNotiList(invocation, noti_cnt); + if (ret_list.size() != static_cast(noti_cnt)) { + LOGE("Read Noti List fail : Expect(%d), Actual(%d)", + noti_cnt, ret_list.size()); + return -1; + } } - g_variant_iter_free(iter); Bundle b(event_info_raw); EventInfo info(b); + if ((info.GetEventType() == EventInfo::Post + || info.GetEventType() == EventInfo::Update) + && (uid >= NORMAL_UID_BASE)) { + info.SetValidatedOwner(util::GetAppId(pid)); + info.SetValidatedUid(uid); + } + dl->parent_->NotifyObserver(info, ret_list); + return 0; +} - if (info.GetEventType() == EventInfo::Post - || info.GetEventType() == EventInfo::Update) { - if (uid >= NORMAL_UID_BASE) { - info.SetValidatedOwner(util::GetAppId(pid)); - info.SetValidatedUid(uid); - } +void DBusEventListener::Impl::MultiNotiUpdateProcess( + GVariant* parameters, GDBusMethodInvocation* invocation, + DBusEventListener::Impl* dl, pid_t pid, uid_t uid) { + int noti_cnt; + char* appid = nullptr; + char* event_info_raw = nullptr; + g_variant_get(parameters, "(&s&si)", &appid, &event_info_raw, ¬i_cnt); + + g_dbus_method_invocation_return_value(invocation, nullptr); + MethodCallHandler( + appid, event_info_raw, noti_cnt, invocation, dl, pid, uid); +} + +void DBusEventListener::Impl::GlobalUpdateProcess( + GVariant* parameters, GDBusMethodInvocation* invocation, + DBusEventListener::Impl* dl, pid_t pid, uid_t uid) { + char* appid = nullptr; + char* event_info_raw = nullptr; + g_variant_get(parameters, "(&s&s)", &appid, &event_info_raw); + g_dbus_method_invocation_return_value(invocation, nullptr); + MethodCallHandler( + appid, event_info_raw, 0, invocation, dl, pid, uid); +} + +void DBusEventListener::Impl::GetProcess( + GVariant* parameters, GDBusMethodInvocation* invocation, + DBusEventListener::Impl* dl) { + char* appid = NULL; + char* serialized = NULL; + g_variant_get(parameters, "(&s&s)", &appid, &serialized); + int recvfd = GetRecvSocket(invocation); + if (recvfd < 1) { + g_dbus_method_invocation_return_error(invocation, + noti_ex_error_quark(), ERROR_IO_ERROR, "Fail to get socket"); + return; } - dl->parent_->NotifyObserver(info, ret_list); + SocketHandler recv_sock(recvfd); + Bundle b(serialized); + EventInfo info(b); + list result = dl->parent_->NotifyObserver(info); + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", result.size())); + for (auto& i : result) { + unsigned int data_size = static_cast( + strlen(reinterpret_cast(i.ToRaw().first.get()))); + int ret = util::WriteSocket(recv_sock.Get(), + reinterpret_cast(&data_size), sizeof(data_size)); + if (ret != 0) { + LOGE("Fail to write (%d)", ret); + break; + } + + ret = util::WriteSocket(recv_sock.Get(), + reinterpret_cast(i.ToRaw().first.get()), data_size); + if (ret != 0) { + LOGE("Fail to write (%d)", ret); + break; + } + } } void DBusEventListener::Impl::OnMethodCall( @@ -269,55 +358,39 @@ void DBusEventListener::Impl::OnMethodCall( GVariant* parameters, GDBusMethodInvocation* invocation, gpointer user_data) { LOGI("method_name[%s] sender[%s]", method_name, sender); - DBusEventListener::Impl* dl = static_cast(user_data); - GVariant* reply_body = NULL; + DBusEventListener::Impl* dl = + static_cast(user_data); try { - char* appid = NULL; - char* serialized = NULL; - uid_t uid = GetSenderUid(conn, sender); pid_t pid = GetSenderPid(conn, sender); if (g_strcmp0(method_name, "Post") == 0 || g_strcmp0(method_name, "Update") == 0 - || g_strcmp0(method_name, "Delete") == 0 - || g_strcmp0(method_name, "Error") == 0 + || g_strcmp0(method_name, "Delete") == 0) { + MultiNotiUpdateProcess(parameters, invocation, dl, pid, uid); + } else if (g_strcmp0(method_name, "Error") == 0 || g_strcmp0(method_name, "DeleteAll") == 0 || g_strcmp0(method_name, "Register") == 0 || g_strcmp0(method_name, "Unregister") == 0) { - parameters = g_variant_ref(parameters); - g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", 0)); - MethodCallHandler(parameters, dl, pid, uid); - g_variant_unref(parameters); - return; + + GlobalUpdateProcess(parameters, invocation, dl, pid, uid); } else if (g_strcmp0(method_name, "Count") == 0) { + char* appid = NULL; + char* serialized = NULL; g_variant_get(parameters, "(&s&s)", &appid, &serialized); Bundle b(serialized); EventInfo info(b); int num = dl->parent_->NotifyNumberRequest(info); - reply_body = g_variant_new("(i)", num); + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", num)); } else if (g_strcmp0(method_name, "Get") == 0) { - g_variant_get(parameters, "(&s&s)", &appid, &serialized); - - Bundle b(serialized); - EventInfo info(b); - list result = dl->parent_->NotifyObserver(info); - GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); - for (auto& i : result) { - g_variant_builder_add(builder, "(s)", - reinterpret_cast(i.ToRaw().first.get())); - } - reply_body = g_variant_new("(a(s))", builder); - g_variant_builder_unref(builder); + GetProcess(parameters, invocation, dl); } else { g_dbus_method_invocation_return_error(invocation, noti_ex_error_quark(), ERROR_IO_ERROR, "invalid operation"); return; } - - g_dbus_method_invocation_return_value(invocation, reply_body); - } catch (Exception &ex) { LOGE("%s %d", ex.what(), ex.GetErrorCode()); g_dbus_method_invocation_return_error(invocation, noti_ex_error_quark(), @@ -337,31 +410,26 @@ int DBusEventListener::Impl::RegisterGDBusInterface() { " " " " " " - " " - " " + " " " " " " " " " " - " " - " " + " " " " " " " " " " - " " - " " + " " " " " " " " " " - " " + " " " " " " " " " " - " " - " " " " " " " " @@ -371,20 +439,14 @@ int DBusEventListener::Impl::RegisterGDBusInterface() { " " " " " " - " " - " " " " " " " " " " - " " - " " " " " " " " " " - " " - " " " " " " " "; diff --git a/notification-ex/dbus_event_listener_implementation.h b/notification-ex/dbus_event_listener_implementation.h index 5fb25da..0bc70e9 100644 --- a/notification-ex/dbus_event_listener_implementation.h +++ b/notification-ex/dbus_event_listener_implementation.h @@ -36,12 +36,25 @@ class DBusEventListener::Impl { private: void UnRegisterGDBusInterface(); int RegisterGDBusInterface(); + std::list ReadNotiList( + GDBusMethodInvocation* invocation, int noti_cnt); + static int GetRecvSocket(GDBusMethodInvocation* invocation); static void OnMethodCall( GDBusConnection *conn, const gchar *sender, const gchar *object_path, const gchar *iface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data); - static void MethodCallHandler(GVariant *parameters, Impl* dl, pid_t pid, uid_t uid); + static int MethodCallHandler(std::string sender_appid, + std::string event_info_raw, int noti_cnt, + GDBusMethodInvocation* invocation, Impl* dl, pid_t pid, uid_t uid); + static void MultiNotiUpdateProcess( + GVariant* parameters, GDBusMethodInvocation* invocation, + Impl* dl, pid_t pid, uid_t uid); + static void GlobalUpdateProcess( + GVariant* parameters, GDBusMethodInvocation* invocation, + Impl* dl, pid_t pid, uid_t uid); + static void GetProcess( + GVariant* parameters, GDBusMethodInvocation* invocation, Impl* dl); static GDBusInterfaceVTable InterfaceVtable; static void SignalCb(GDBusConnection* connection, diff --git a/notification-ex/dbus_sender.cc b/notification-ex/dbus_sender.cc index 202a072..36bce5c 100644 --- a/notification-ex/dbus_sender.cc +++ b/notification-ex/dbus_sender.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,7 @@ #include "notification-ex/dbus_sender_implementation.h" #include "notification-ex/event_info_internal.h" #include "notification-ex/ex_util.h" +#include "notification-ex/socket_handler.h" #ifdef LOG_TAG #undef LOG_TAG @@ -34,6 +36,9 @@ #define LOG_TAG "NOTIFICATION_EX" #define MAX_PACKAGE_STR_SIZE 512 +#define RECV_SOCK_IDX 0 +#define SEND_SOCK_IDX 1 + using namespace std; using namespace tizen_base; namespace notification { @@ -89,17 +94,10 @@ string DBusSender::Impl::GetBusName(string appid, string dest_appid) const { return DBusConnectionManager::GetInst().GetBusName(dest_appid); } -void DBusSender::Notify(const IEventInfo& info, list serialized, - string dest_appid) { +void DBusSender::Notify(GVariantBuilder* builder, + const IEventInfo& info, string dest_appid) { string signal_name = EventInfo::GetString(info.GetEventType()); string appid = util::GetAppId(); - - GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); - for (auto& i : serialized) { - g_variant_builder_add(builder, "(s)", - reinterpret_cast(i.ToRaw().first.get())); - } - GVariant* data = g_variant_new("(ssa(s))", appid.c_str(), reinterpret_cast(info.Serialize().ToRaw().first.get()), builder); @@ -109,6 +107,24 @@ void DBusSender::Notify(const IEventInfo& info, list serialized, g_variant_builder_unref(builder); } +void DBusSender::Notify(const IEventInfo& info, list serialized, + string dest_appid) { + GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); + int idx = 0; + for (auto& i : serialized) { + if (idx != 0 && idx % 10 == 0) { + Notify(builder, info, dest_appid); + g_variant_builder_unref(builder); + builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); + } + g_variant_builder_add(builder, "(s)", + reinterpret_cast(i.ToRaw().first.get())); + idx++; + } + Notify(builder, info, dest_appid); +} + + GDBusMessage* DBusSender::Impl::MethodCall(string appid, string method_name, Bundle serialized) { GDBusMessage* msg = g_dbus_message_new_method_call( @@ -124,9 +140,7 @@ GDBusMessage* DBusSender::Impl::MethodCall(string appid, string method_name, g_dbus_message_set_body(msg, g_variant_new("(ss)", appid.c_str(), - reinterpret_cast(serialized.ToRaw().first.get()) - ) - ); + reinterpret_cast(serialized.ToRaw().first.get()))); LOGI("send message !! (%s) (%s) (%s)", path_.c_str(), method_name.c_str(), appid.c_str()); @@ -148,8 +162,92 @@ GDBusMessage* DBusSender::Impl::MethodCall(string appid, string method_name, return reply; } +std::list DBusSender::Impl::MethodCallWithSocket( + string appid, string method_name, Bundle serialized) { + list ret_list; + int fds[2]; + int ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds); + if (ret < 0) { + LOGE("socketpair [%d]", ret); + return ret_list; + } + SocketHandler send_sock(fds[SEND_SOCK_IDX]); + SocketHandler recv_sock(fds[RECV_SOCK_IDX]); + std::unique_ptr fd_list_ptr( + GetFdList(send_sock.Get()), g_object_unref); + + + std::unique_ptr msg_ptr( + g_dbus_message_new_method_call( + DBusConnectionManager::GetInst().GetDataProviderMasterName().c_str(), + path_.c_str(), + DBusConnectionManager::GetInst().GetInterfaceName().c_str(), + method_name.c_str()), + g_object_unref); + if (!msg_ptr || !msg_ptr.get()) { + LOGE("Can't allocate new method call"); + return ret_list; + } + + g_dbus_message_set_unix_fd_list(msg_ptr.get(), fd_list_ptr.get()); + g_dbus_message_set_body(msg_ptr.get(), + g_variant_new("(ss)", + appid.c_str(), + reinterpret_cast(serialized.ToRaw().first.get()))); + + LOGI("send message !! (%s) (%s) (%s)", + path_.c_str(), method_name.c_str(), appid.c_str()); + + GError* err = nullptr; + std::unique_ptr reply_ptr( + g_dbus_connection_send_message_with_reply_sync( + DBusConnectionManager::GetInst().GetConnection(), msg_ptr.get(), + G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err), + g_object_unref); + if (err != NULL) { + LOGE("MethodCall, err[%s]", err->message); + if (err->code == G_DBUS_ERROR_ACCESS_DENIED) + set_last_result(ERROR_PERMISSION_DENIED); + else + set_last_result(ERROR_IO_ERROR); + g_error_free(err); + } else if (CheckReplyMessage(reply_ptr.get()) == 0) { + GVariant *reply_body = g_dbus_message_get_body(reply_ptr.get()); + int cnt; + g_variant_get(reply_body, "(i)", &cnt); + ret_list = util::ReadBundleList(recv_sock.Get(), cnt); + } + return ret_list; +} + +GUnixFDList* DBusSender::Impl::GetFdList(int fd) { + GError* g_err = nullptr; + GUnixFDList* fd_list = g_unix_fd_list_new(); + g_unix_fd_list_append(fd_list, fd, &g_err); + if (g_err != nullptr) { + LOGE("g_unix_fd_list_append [%s]", g_err->message); + g_object_unref(fd_list); + g_error_free(g_err); + return nullptr; + } + return fd_list; +} + GDBusMessage* DBusSender::Impl::MethodCall(string appid, const IEventInfo& info, list serialized) { + int fds[2]; + int ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds); + if (ret < 0) { + LOGE("socketpair [%d]", ret); + return nullptr; + } + + SocketHandler send_sock(fds[SEND_SOCK_IDX]); + SocketHandler recv_sock(fds[RECV_SOCK_IDX]); + GUnixFDList* fd_list = GetFdList(recv_sock.Get()); + auto fd_list_ptr = std::unique_ptr( + fd_list, g_object_unref); + GDBusMessage* msg = g_dbus_message_new_method_call( DBusConnectionManager::GetInst().GetDataProviderMasterName().c_str(), path_.c_str(), @@ -160,22 +258,16 @@ GDBusMessage* DBusSender::Impl::MethodCall(string appid, const IEventInfo& info, return nullptr; } - GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); - for (auto& i : serialized) { - g_variant_builder_add(builder, "(s)", - reinterpret_cast(i.ToRaw().first.get())); - } - + g_dbus_message_set_unix_fd_list(msg, fd_list); g_dbus_message_set_body(msg, - g_variant_new("(ssa(s))", + g_variant_new("(ssi)", appid.c_str(), reinterpret_cast(info.Serialize().ToRaw().first.get()), - builder - ) - ); + serialized.size())); LOGI("send message !! (%s) (%s) (%s)", - path_.c_str(), EventInfo::GetString(info.GetEventType()).c_str(), appid.c_str()); + path_.c_str(), + EventInfo::GetString(info.GetEventType()).c_str(), appid.c_str()); GError* err = nullptr; GDBusMessage* reply = g_dbus_connection_send_message_with_reply_sync( @@ -188,9 +280,21 @@ GDBusMessage* DBusSender::Impl::MethodCall(string appid, const IEventInfo& info, else set_last_result(ERROR_IO_ERROR); g_error_free(err); + } else { + for (auto& i : serialized) { + unsigned int data_size = static_cast( + strlen(reinterpret_cast(i.ToRaw().first.get()))); + int ret = util::WriteSocket(send_sock.Get(), + reinterpret_cast(&data_size), sizeof(data_size)); + if (ret != 0) + break; + ret = util::WriteSocket(send_sock.Get(), + reinterpret_cast(i.ToRaw().first.get()), data_size); + if (ret != 0) + break; + } } - g_variant_builder_unref(builder); g_object_unref(msg); return reply; } @@ -222,27 +326,10 @@ int DBusSender::SendMessage(const IEventInfo& info, list serialized, set_last_result(ERROR_NONE); } - GVariant *reply_body = g_dbus_message_get_body(reply); - g_variant_get(reply_body, "(i)", &ret); - return ret; + return 0; } -std::list DBusSender::Request(const IEventInfo& info) { - string appid = info.GetOwner(); - if (appid.length() == 0) - appid = util::GetAppId(); - - string method_name = EventInfo::GetString(info.GetEventType()); - Bundle serialized = info.Serialize(); - - list ret_list; - GDBusMessage* reply = impl_->MethodCall(appid, method_name, serialized); - if (!reply) - return ret_list; - - auto reply_ptr = std::unique_ptr( - reply, g_object_unref); - +int DBusSender::Impl::CheckReplyMessage(GDBusMessage* reply) { GError* err = nullptr; if (g_dbus_message_to_gerror(reply, &err)) { LOGE("Request got error %s", err->message); @@ -252,26 +339,24 @@ std::list DBusSender::Request(const IEventInfo& info) { set_last_result(ERROR_IO_ERROR); g_error_free(err); - return ret_list; + return -1; } else { set_last_result(ERROR_NONE); } + return 0; +} - GVariant *reply_body = g_dbus_message_get_body(reply); - GVariantIter *iter = nullptr; - g_variant_get(reply_body, "(a(s))", &iter); - char* raw = nullptr; - while (g_variant_iter_loop(iter, "(&s)", &raw) && raw != nullptr) { - Bundle ret(raw); - ret_list.emplace_back(ret); - } +std::list DBusSender::Request(const IEventInfo& info) { + string appid = info.GetOwner(); + if (appid.length() == 0) + appid = util::GetAppId(); - if (iter) - g_variant_iter_free(iter); - return ret_list; + string method_name = EventInfo::GetString(info.GetEventType()); + Bundle serialized = info.Serialize(); + return impl_->MethodCallWithSocket(appid, method_name, serialized); } -int DBusSender::RequestNumber(const IEventInfo& info) { +int DBusSender::RequestReturnValue(const IEventInfo& info) { string appid = info.GetOwner(); if (appid.length() == 0) appid = util::GetAppId(); @@ -288,7 +373,7 @@ int DBusSender::RequestNumber(const IEventInfo& info) { GError* err = nullptr; if (g_dbus_message_to_gerror(reply, &err)) { - LOGE("RequestNumber got error %s", err->message); + LOGE("RequestReturnValue got error %s", err->message); if (err->code == G_DBUS_ERROR_ACCESS_DENIED) set_last_result(ERROR_PERMISSION_DENIED); else diff --git a/notification-ex/dbus_sender.h b/notification-ex/dbus_sender.h index 894cc57..2198459 100644 --- a/notification-ex/dbus_sender.h +++ b/notification-ex/dbus_sender.h @@ -40,7 +40,11 @@ class EXPORT_API DBusSender : public IEventSender { int SendMessage(const IEventInfo& info, std::list serialized, std::string dest_appid = "") override; std::list Request(const IEventInfo& info) override; - int RequestNumber(const IEventInfo& info) override; + int RequestReturnValue(const IEventInfo& info) override; + + private: + void Notify(GVariantBuilder* builder, + const IEventInfo& info, std::string dest_appid); private: class Impl; diff --git a/notification-ex/dbus_sender_implementation.h b/notification-ex/dbus_sender_implementation.h index d7f0d5b..7d1c501 100644 --- a/notification-ex/dbus_sender_implementation.h +++ b/notification-ex/dbus_sender_implementation.h @@ -39,11 +39,16 @@ class DBusSender::Impl { private: std::string GetBusName( std::string appid, std::string dest_appid) const; - bool EmitSignal(std::string bus_name, std::string signal_name, GVariant* data); + bool EmitSignal(std::string bus_name, + std::string signal_name, GVariant* data); GDBusMessage* MethodCall(std::string appid, std::string method_name, tizen_base::Bundle serialized); GDBusMessage* MethodCall(std::string appid, const IEventInfo& info, std::list serialized); + std::list MethodCallWithSocket(std::string appid, + std::string method_name, tizen_base::Bundle serialized); + GUnixFDList* GetFdList(int fd); + int CheckReplyMessage(GDBusMessage* reply); std::string path_; DBusSender* parent_; }; diff --git a/notification-ex/event_sender_interface.h b/notification-ex/event_sender_interface.h index 523d656..ed2e965 100644 --- a/notification-ex/event_sender_interface.h +++ b/notification-ex/event_sender_interface.h @@ -40,7 +40,7 @@ class EXPORT_API IEventSender { std::list serialized, std::string dest_appid = "") = 0; virtual std::list Request(const IEventInfo& info) = 0; - virtual int RequestNumber(const IEventInfo& info) = 0; + virtual int RequestReturnValue(const IEventInfo& info) = 0; }; } // namespace notification diff --git a/notification-ex/ex_util.cc b/notification-ex/ex_util.cc index 07e5b55..2b796e5 100644 --- a/notification-ex/ex_util.cc +++ b/notification-ex/ex_util.cc @@ -26,16 +26,22 @@ #include #include "notification-ex/ex_util.h" +#include "notification-ex/socket_handler.h" #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "NOTIFICATION_EX" -#define MAX_PACKAGE_STR_SIZE 512 -#define MAX_CACHE_SIZE 100 using namespace std; + +namespace { +constexpr int MAX_PACKAGE_STR_SIZE = 512; +constexpr int MAX_CACHE_SIZE = 100; +constexpr int MAX_RETRY_CNT = 10; +} + namespace notification { namespace util { @@ -46,7 +52,7 @@ int GetRequestId() { } string GetAppId() { - return GetAppId(getpid()); + return GetAppId(getpid()); } string GetAppId(pid_t pid) { @@ -179,5 +185,110 @@ string GetLocaleDirectory() { return locale_directory; } +unsigned int GetSocketBufferSize(int fd, int optname) { + unsigned int ret_size = 0; + socklen_t len = sizeof(ret_size); + + errno = 0; + if (getsockopt(fd, SOL_SOCKET, optname, &ret_size, &len) < 0) { + LOGE("read socket size [%d]", errno); + return 0; + } + return ret_size; +} + +unsigned int ReadSocket(int fd, char* buffer, unsigned int nbytes) { + unsigned int left = nbytes; + ssize_t nb; + int retry_cnt = 0; + const struct timespec SLEEP_TIME = { 0, 20 * 1000 * 1000 }; + while (left && (retry_cnt < MAX_RETRY_CNT)) { + errno = 0; + nb = read(fd, buffer, left); + if (nb == 0) { + LOGE("read socket - EOF, fd close [%d]", fd); + return -1; + } else if (nb == -1) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + LOGE("errno [%d], sleep and retry", errno); + retry_cnt++; + nanosleep(&SLEEP_TIME, 0); + continue; + } + LOGE("errno [%d] fd [%d]", errno, fd); + return -1; + } + left -= nb; + buffer += nb; + retry_cnt = 0; + } + + if (left != 0) { + LOGE("error fd [%d] retry_cnt [%d]", fd, retry_cnt); + return -1; + } + return 0; +} + +list ReadBundleList(int recvfd, int noti_cnt) { + list ret_list; + list empty_list; + SocketHandler recv_sock(recvfd); + unsigned int buf_size = 0; + unsigned int data_size = 0; + buf_size = util::GetSocketBufferSize(recv_sock.Get(), SO_RCVBUF); + std::unique_ptr data_ptr( + static_cast(calloc(buf_size, sizeof(char))), std::free); + for (int i = 0; i < noti_cnt; i++) { + int ret = util::ReadSocket(recv_sock.Get(), + reinterpret_cast(&data_size), sizeof(data_size)); + if (ret != 0) + return empty_list; + if (data_size > buf_size) { + buf_size = data_size; + data_ptr.reset(static_cast(calloc(buf_size, sizeof(char)))); + } + memset(data_ptr.get(), 0, buf_size); + ret = util::ReadSocket(recv_sock.Get(), data_ptr.get(), data_size); + if (ret != 0) + return empty_list; + ret_list.emplace_back(data_ptr.get()); + } + return ret_list; +} + +int WriteSocket(int fd, const char* buffer, unsigned int nbytes) { + int retry_cnt = 0; + unsigned int left = nbytes; + ssize_t nb; + const struct timespec SLEEP_TIME = { 0, 20 * 1000 * 1000 }; + + while (left && (retry_cnt < MAX_RETRY_CNT)) { + errno = 0; + nb = write(fd, buffer, left); + if (nb == -1) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + LOGE("continue.."); + retry_cnt++; + nanosleep(&SLEEP_TIME, 0); + continue; + } + LOGE("error fd [%d] errno [%d]", fd, errno); + return -1; + } + + left -= nb; + buffer += nb; + retry_cnt = 0; + } + + if (left != 0) { + LOGE("error fd [%d], retry_cnt [%d]", fd, retry_cnt); + return -1; + } + return 0; +} + + } // namespace util } // namespace notification diff --git a/notification-ex/ex_util.h b/notification-ex/ex_util.h index c4fa466..1906695 100644 --- a/notification-ex/ex_util.h +++ b/notification-ex/ex_util.h @@ -18,8 +18,12 @@ #define NOTIFICATION_EX_EX_UTIL_H_ #include +#include +#include +#include #include +#include namespace notification { namespace util { @@ -29,6 +33,10 @@ namespace util { std::string GetPkgId(); std::string GetDomainName(); std::string GetLocaleDirectory(); + unsigned int GetSocketBufferSize(int fd, int optname); + unsigned int ReadSocket(int fd, char* buffer, unsigned int nbytes); + int WriteSocket(int fd, const char* buffer, unsigned int nbytes); + std::list ReadBundleList(int recvfd, int noti_cnt); } // namespace util } // namespace notification diff --git a/notification-ex/manager.cc b/notification-ex/manager.cc index e8fab13..b5e243d 100644 --- a/notification-ex/manager.cc +++ b/notification-ex/manager.cc @@ -52,10 +52,8 @@ Manager::~Manager() = default; Manager::Impl::~Impl() { listener_->UnRegisterObserver(parent_); - - list serialized_list {}; EventInfo info(EventInfo::Unregister, util::GetAppId(), "", ""); - sender_->SendMessage(info, serialized_list, DATA_PROVIDER_MASTER_ID); + sender_->RequestReturnValue(info); } Manager::Impl::Impl(Manager* parent, unique_ptr sender, @@ -69,9 +67,8 @@ Manager::Impl::Impl(Manager* parent, if (DBusConnectionManager::GetInst().IsDataProviderMaster(util::GetAppId())) return; - list serialized_list {}; EventInfo info(EventInfo::Register, util::GetAppId(), receiver_group, ""); - sender_->SendMessage(info, serialized_list, DATA_PROVIDER_MASTER_ID); + sender_->RequestReturnValue(info); } int Manager::Impl::SendNotify(shared_ptr noti, @@ -90,69 +87,66 @@ void Manager::SendError(const IEventInfo& info, NotificationError error) { IEventInfo& i = const_cast(info); static_cast(i).SetError(error); static_cast(i).SetEventType(EventInfo::Error); - impl_->sender_->SendMessage(info, serialized_list, info.GetOwner()); + impl_->sender_->Notify(info, serialized_list, info.GetOwner()); } int Manager::Update(shared_ptr noti, int& request_id) { Bundle serialized = noti->Serialize(); - EventInfo info(EventInfo::Update, util::GetAppId(), noti->GetChannel(), noti->GetId()); + EventInfo info( + EventInfo::Update, util::GetAppId(), noti->GetChannel(), noti->GetId()); list serialized_list {serialized}; request_id = info.GetRequestId(); - return impl_->sender_->SendMessage(info, serialized_list, noti->GetSenderAppId()); + return impl_->sender_->SendMessage( + info, serialized_list, noti->GetSenderAppId()); } int Manager::Delete(shared_ptr noti, int& request_id) { Bundle serialized = noti->Serialize(); - EventInfo info(EventInfo::Delete, util::GetAppId(), noti->GetChannel(), noti->GetId()); + EventInfo info( + EventInfo::Delete, util::GetAppId(), noti->GetChannel(), noti->GetId()); list serialized_list {serialized}; request_id = info.GetRequestId(); - return impl_->sender_->SendMessage(info, serialized_list, noti->GetSenderAppId()); + return impl_->sender_->SendMessage( + info, serialized_list, noti->GetSenderAppId()); } int Manager::DeleteAll(int& request_id) { - Bundle serialized; EventInfo info(EventInfo::DeleteAll, util::GetAppId(), ""); - list serialized_list {serialized}; - request_id = info.GetRequestId(); - return impl_->sender_->SendMessage(info, serialized_list, util::GetAppId()); + return impl_->sender_->RequestReturnValue(info); } int Manager::DeleteByChannel(string channel, int& request_id) { - Bundle serialized; EventInfo info(EventInfo::DeleteAll, util::GetAppId(), channel); - list serialized_list {serialized}; - request_id = info.GetRequestId(); - return impl_->sender_->SendMessage(info, serialized_list, util::GetAppId()); + return impl_->sender_->RequestReturnValue(info); } int Manager::DeleteByAppId(string appId, int& request_id) { - Bundle serialized; EventInfo info(EventInfo::DeleteAll, util::GetAppId(), "", appId); - list serialized_list {serialized}; - request_id = info.GetRequestId(); - return impl_->sender_->SendMessage(info, serialized_list, util::GetAppId()); + return impl_->sender_->RequestReturnValue(info); } int Manager::GetCount() const { EventInfo info(EventInfo::Count, util::GetAppId(), ""); - int num = impl_->sender_->RequestNumber(info); - return num; + return impl_->sender_->RequestReturnValue(info); } int Manager::Hide(shared_ptr noti, int& request_id) { - (reinterpret_cast(noti->GetInfo().get()))->AddHideViewer(util::GetAppId()); + (reinterpret_cast(noti->GetInfo().get())) + ->AddHideViewer(util::GetAppId()); - EventInfo info(EventInfo::Update, util::GetAppId(), noti->GetChannel(), noti->GetId()); + EventInfo info( + EventInfo::Update, util::GetAppId(), noti->GetChannel(), noti->GetId()); Bundle serialized = noti->Serialize(); list serialized_list {serialized}; request_id = info.GetRequestId(); - return impl_->sender_->SendMessage(info, serialized_list, noti->GetSenderAppId()); + return impl_->sender_->SendMessage( + info, serialized_list, noti->GetSenderAppId()); } unique_ptr Manager::FindByRootID(string id) { @@ -295,7 +289,8 @@ void Manager::OnDelete(const IEventInfo& info, void Manager::OnError(NotificationError error, int requestId) { } -list> Manager::OnRequestEvent(const IEventInfo& info) { +list> Manager::OnRequestEvent( + const IEventInfo& info) { return list>({}); } diff --git a/notification-ex/reporter.cc b/notification-ex/reporter.cc index c8cef07..7e03f69 100644 --- a/notification-ex/reporter.cc +++ b/notification-ex/reporter.cc @@ -72,7 +72,7 @@ void Reporter::SendError(const IEventInfo& info, NotificationError error) { IEventInfo& i = const_cast(info); static_cast(i).SetError(error); static_cast(i).SetEventType(EventInfo::Error); - impl_->sender_->SendMessage(info, serialized_list, info.GetOwner()); + impl_->sender_->Notify(info, serialized_list, info.GetOwner()); } int Reporter::Post(std::shared_ptr noti, int& request_id) { @@ -80,7 +80,8 @@ int Reporter::Post(std::shared_ptr noti, int& request_id) { static_pointer_cast(noti->GetInfo())->SetTime(time(NULL)); Bundle serialized = noti->Serialize(); - EventInfo info(EventInfo::Post, util::GetAppId(), noti->GetChannel(), noti->GetId()); + EventInfo info( + EventInfo::Post, util::GetAppId(), noti->GetChannel(), noti->GetId()); list serialized_list {serialized}; SharedFile::CopyPrivateFile(noti); @@ -88,7 +89,8 @@ int Reporter::Post(std::shared_ptr noti, int& request_id) { return impl_->sender_->SendMessage(info, serialized_list); } -int Reporter::Post(std::list> notiList, int& request_id) { +int Reporter::Post( + std::list> notiList, int& request_id) { LOGI("Post noti list"); EventInfo info(EventInfo::Post, util::GetAppId(), ""); list serialized_list; @@ -107,7 +109,8 @@ int Reporter::Update(std::shared_ptr noti, int& request_id) { static_pointer_cast(noti->GetInfo())->SetTime(time(NULL)); Bundle serialized = noti->Serialize(); - EventInfo info(EventInfo::Update, util::GetAppId(), noti->GetChannel(), noti->GetId()); + EventInfo info( + EventInfo::Update, util::GetAppId(), noti->GetChannel(), noti->GetId()); list serialized_list {serialized}; SharedFile::CopyPrivateFile(noti); @@ -115,7 +118,8 @@ int Reporter::Update(std::shared_ptr noti, int& request_id) { return impl_->sender_->SendMessage(info, serialized_list); } -int Reporter::Update(std::list> notiList, int& request_id) { +int Reporter::Update( + std::list> notiList, int& request_id) { EventInfo info(EventInfo::Update, util::GetAppId(), ""); list serialized_list; for (auto& i : notiList) { @@ -131,14 +135,17 @@ int Reporter::Update(std::list> notiList, int& req int Reporter::Delete(std::shared_ptr noti, int& request_id) { Bundle serialized = noti->Serialize(); - EventInfo info(EventInfo::Delete, util::GetAppId(), noti->GetChannel(), noti->GetId()); + EventInfo info( + EventInfo::Delete, util::GetAppId(), noti->GetChannel(), noti->GetId()); list serialized_list {serialized}; request_id = info.GetRequestId(); - return impl_->sender_->SendMessage(info, serialized_list, noti->GetSenderAppId()); + return impl_->sender_->SendMessage( + info, serialized_list, noti->GetSenderAppId()); } -int Reporter::Delete(std::list> notiList, int& request_id) { +int Reporter::Delete( + std::list> notiList, int& request_id) { EventInfo info(EventInfo::Delete, util::GetAppId(), ""); list serialized_list; for (auto& i : notiList) { @@ -153,25 +160,18 @@ int Reporter::Delete(std::list> notiList, int& req } int Reporter::DeleteAll(int& request_id) { - Bundle serialized; EventInfo info(EventInfo::DeleteAll, util::GetAppId(), ""); - list serialized_list {serialized}; - request_id = info.GetRequestId(); - return impl_->sender_->SendMessage(info, serialized_list, util::GetAppId()); + return impl_->sender_->RequestReturnValue(info); } int Reporter::DeleteByChannel(string channel, int& request_id) { - Bundle serialized; EventInfo info(EventInfo::DeleteAll, util::GetAppId(), channel); - list serialized_list {serialized}; - request_id = info.GetRequestId(); - return impl_->sender_->SendMessage(info, serialized_list, util::GetAppId()); + return impl_->sender_->RequestReturnValue(info); } std::unique_ptr Reporter::FindByRootID(std::string id) { - Bundle serialized; EventInfo info(EventInfo::Get, util::GetAppId(), "", id); list result = impl_->sender_->Request(info); if (result.size() == 0) { @@ -184,7 +184,6 @@ std::unique_ptr Reporter::FindByRootID(std::string id) { } list> Reporter::FindByChannel(string channel) { - Bundle serialized; EventInfo info(EventInfo::Get, util::GetAppId(), channel, ""); list result = impl_->sender_->Request(info); if (result.size() == 0) { @@ -200,7 +199,6 @@ list> Reporter::FindByChannel(string channel) { } list> Reporter::FindAll() { - Bundle serialized; EventInfo info(EventInfo::Get, util::GetAppId(), "", ""); list result = impl_->sender_->Request(info); if (result.size() == 0) { @@ -217,8 +215,7 @@ list> Reporter::FindAll() { int Reporter::GetCount(string channel) const { EventInfo info(EventInfo::Count, util::GetAppId(), channel); - int num = impl_->sender_->RequestNumber(info); - return num; + return impl_->sender_->RequestReturnValue(info); } int Reporter::SendEvent(const IEventInfo& info, @@ -251,7 +248,8 @@ void Reporter::OnEvent(const IEventInfo& info, list serialized) { OnEvent(info, item_list); } -list> Reporter::OnRequestEvent(const IEventInfo& info) { +list> Reporter::OnRequestEvent( + const IEventInfo& info) { return list>({}); } diff --git a/notification-ex/socket_handler.h b/notification-ex/socket_handler.h new file mode 100644 index 0000000..aa9747f --- /dev/null +++ b/notification-ex/socket_handler.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 Samsung Electronics 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 NOTIFICATION_EX_SOCKET_HANDLER_H_ +#define NOTIFICATION_EX_SOCKET_HANDLER_H_ + +#include + +namespace notification { + +class SocketHandler { + public: + SocketHandler(int fd):fd_(fd){} + ~SocketHandler() { + if(fd_!=-1) + close(fd_); + } + operator int() const { return fd_; } + int Get() { + return fd_; + } + + private: + int fd_ = -1; +}; + +} // namespace notification +#endif // NOTIFICATION_EX_SOCKET_HANDLER_H_ \ No newline at end of file diff --git a/notification-ex/stub.cc b/notification-ex/stub.cc index f79ebdb..68cb4b4 100644 --- a/notification-ex/stub.cc +++ b/notification-ex/stub.cc @@ -2810,7 +2810,12 @@ extern "C" EXPORT_API int noti_ex_manager_delete_all(noti_ex_manager_h handle, } try { ManagerStub* stub = static_cast(handle); - ret = stub->DeleteAll(*request_id); + stub->DeleteAll(*request_id); + ret = get_last_result(); + if (ret != ERROR_NONE) { + LOGE("error(%d)", ret); + return ret; + } } catch (Exception &ex) { LOGE("%s %d", ex.what(), ex.GetErrorCode()); return NOTI_EX_ERROR_IO_ERROR; @@ -2829,7 +2834,12 @@ extern "C" EXPORT_API int noti_ex_manager_delete_by_channel( try { ManagerStub* stub = static_cast(handle); - ret = stub->DeleteByChannel(channel, *request_id); + stub->DeleteByChannel(channel, *request_id); + ret = get_last_result(); + if (ret != ERROR_NONE) { + LOGE("error(%d)", ret); + return ret; + } } catch (Exception &ex) { LOGE("%s %d", ex.what(), ex.GetErrorCode()); return NOTI_EX_ERROR_IO_ERROR; @@ -2849,7 +2859,12 @@ extern "C" EXPORT_API int noti_ex_manager_delete_by_appid( try { ManagerStub* stub = static_cast(handle); - ret = stub->DeleteByAppId(app_id, *request_id); + stub->DeleteByAppId(app_id, *request_id); + ret = get_last_result(); + if (ret != ERROR_NONE) { + LOGE("error(%d)", ret); + return ret; + } } catch (Exception &ex) { LOGE("%s %d", ex.what(), ex.GetErrorCode()); return NOTI_EX_ERROR_IO_ERROR; @@ -3294,7 +3309,12 @@ extern "C" EXPORT_API int noti_ex_reporter_delete_all( try { ReporterStub* stub = static_cast(handle); - ret = stub->DeleteAll(*request_id); + stub->DeleteAll(*request_id); + ret = get_last_result(); + if (ret != ERROR_NONE) { + LOGE("error(%d)", ret); + return ret; + } } catch (Exception &ex) { LOGE("%s %d", ex.what(), ex.GetErrorCode()); return NOTI_EX_ERROR_IO_ERROR; @@ -3314,7 +3334,12 @@ extern "C" EXPORT_API int noti_ex_reporter_delete_by_channel( try { ReporterStub* stub = static_cast(handle); - ret = stub->DeleteByChannel(channel, *request_id); + stub->DeleteByChannel(channel, *request_id); + ret = get_last_result(); + if (ret != ERROR_NONE) { + LOGE("error(%d)", ret); + return ret; + } } catch (Exception &ex) { LOGE("%s %d", ex.what(), ex.GetErrorCode()); return NOTI_EX_ERROR_IO_ERROR; -- cgit v1.2.3