From c4d944349508e7480b7b55e2503b7b1d0b1452d5 Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Wed, 16 Nov 2016 11:38:50 +0100 Subject: [PATCH] Switch askuser-notification to server from client askuser-notification systemd services will work as socket servers accepting requests to fetch user answer from popup. New service is socket activated. Socket and systemd unit are created per user instance. This change is only partial. Switch of askuser notification backend is required and will be provided with next commit. Change-Id: I989312e36fd5aded2a8fdda52f4c72a745e35807 --- src/agent/notification-daemon/AskUserTalker.cpp | 281 ++++++++++++++++++------ src/agent/notification-daemon/AskUserTalker.h | 29 ++- src/agent/notification-daemon/GuiRunner.cpp | 181 +++++++++------ src/agent/notification-daemon/GuiRunner.h | 64 +++--- src/agent/notification-daemon/main.cpp | 3 +- src/common/socket/Socket.cpp | 36 ++- src/common/socket/Socket.h | 8 +- 7 files changed, 422 insertions(+), 180 deletions(-) diff --git a/src/agent/notification-daemon/AskUserTalker.cpp b/src/agent/notification-daemon/AskUserTalker.cpp index ef86693..32e099b 100644 --- a/src/agent/notification-daemon/AskUserTalker.cpp +++ b/src/agent/notification-daemon/AskUserTalker.cpp @@ -14,15 +14,17 @@ * limitations under the License */ /** - * @file src/notification-daemon/GuiRunner.h + * @file src/agent/notification-daemon/AskUserTalker.cpp * @author Oskar Świtalski + * @author Zofia Abramowska * @brief Definition of AskUserTalker class */ #include "AskUserTalker.h" -#include +#include #include +#include #include "Policy.h" #include "PrivilegeInfo.h" @@ -30,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -39,6 +40,9 @@ #include +#ifdef BUILD_WITH_SYSTEMD_DAEMON +#include +#endif namespace AskUser { @@ -55,6 +59,10 @@ void setSecurityLevel(const std::string &app, const std::string &perm, const std ALOGD("SecurityManager: Setting security level to " << level); std::string appName; identifyApp(app, appName); + if (appName.empty()) { + ALOGE("Couldn't fetch appName from cynara client. Cannot set policy"); + return; + } std::string privacyName = PrivilegeInfo::getPrivacyName(perm); if (privacyName.empty()) { @@ -86,15 +94,81 @@ void setSecurityLevel(const std::string &app, const std::string &perm, const std } /* namespace */ +void AskUserTalker::dissmissCb(int fd, void *data) { + AskUserTalker *talker = static_cast(data); + if (fd == talker->m_currentPeerSocket.getFd()) { + ALOGD("Client behaved incorrectly"); + // I would close client socket here but ecore loop doesn't like closing fd while in handler + } else if (fd == talker->m_signalSocket.getFd()) { + ALOGD("Got signal to close"); + talker->m_running = false; + } +} + +AskUserTalker::AskUserTalker() + : m_poller(2), + m_signalSocket(Socket::PeerType::SIGNAL), + m_serverSocket(Socket::PeerType::SERVER), + m_currentPeerSocket(Socket::PeerType::PEER) +{} + +void AskUserTalker::setSignalDescriptor() { + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + + if (pthread_sigmask(SIG_BLOCK, &mask, NULL) < 0) { + throw ErrnoException("Couldn't set signal mask"); + } + + int signalFd = signalfd(-1, &mask, 0); + if (signalFd < 0) { + throw ErrnoException("Couldn't create signalfd"); + } + + m_signalSocket.setFd(signalFd); + m_poller.setEvents(m_signalSocket.getFd(), POLLIN); + + ALOGD("Signal descriptor set for " << m_signalSocket.getFd()); +} + +void AskUserTalker::init() { +#ifdef BUILD_WITH_SYSTEMD_DAEMON + int systemdFdCount = sd_listen_fds(0); + if (systemdFdCount < 0) { + ALOGE("Error in sd_listen_fds"); + throw Exception("Couldn't setup systemd socket"); + } + if (systemdFdCount > 1) { + ALOGE("Systemd passed to many sockets"); + throw Exception("Too many sockets passed"); + } + + m_serverSocket.setFd(SD_LISTEN_FDS_START); + if (m_serverSocket.getFd() == -1) { + ALOGE("Failed to set socket fd from systemd"); + throw Exception("Cannot set socket from systemd"); + } -AskUserTalker::AskUserTalker(GuiRunner *gui) : m_clientSocket(Socket::PeerType::CLIENT), m_gui(gui) { - m_gui->setDropHandler([&](){return this->shouldDismiss();}); + int ret = sd_notify(0, "READY=1"); + if (ret == 0) { + ALOGW("Agent was not configured to notify its status"); + } else if (ret < 0) { + ALOGE("sd_notify failed: [" << ret << "]"); + } +#else + m_serverSocket.bindAndListen(Path::getUserSocketPath(getuid())); +#endif + m_poller.setEvents(m_serverSocket.getFd(), POLLIN); + setSignalDescriptor(); + m_gui.initialize(); + ALOGD("Initialized"); } bool AskUserTalker::fetchRequest(NotificationRequest &request) { std::string requestData; - if (!m_clientSocket.recv(requestData)) { + if (!m_currentPeerSocket.recv(requestData)) { ALOGI("Failed fetching request, closing..."); return false; } @@ -106,91 +180,164 @@ bool AskUserTalker::fetchRequest(NotificationRequest &request) { } bool AskUserTalker::sendResponse(const NotificationResponse &response) { - if (!m_clientSocket.send(static_cast(response.id))) { + if (!m_currentPeerSocket.send(static_cast(response.id))) { ALOGI("Askuserd closed connection, closing..."); return false; } - if (!m_clientSocket.send(static_cast(response.response))) { + if (!m_currentPeerSocket.send(static_cast(response.response))) { ALOGI("Askuserd closed connection, closing..."); return false; } return true; } -void AskUserTalker::run() -{ - m_clientSocket.connect(Path::getSocketPath()); +void AskUserTalker::handlePeer() { + NotificationRequest request; + if (!fetchRequest(request)) { + ALOGE("Couldn't fetch request, closing..."); + return; + } - while (!stopFlag) { - ALOGD("Waiting for request..."); - NotificationRequest request; - if (!fetchRequest(request)) { - ALOGE("Couldn't fetch request, closing..."); - break; - } + m_gui.addDismissFd(m_currentPeerSocket.getFd(), AskUserTalker::dissmissCb, this); - NotificationResponse response; - response.response = m_gui->popupRun(request.data.client, - PrivilegeInfo::getPrivilegeDisplayName(request.data.privilege)); - response.id = request.id; + NotificationResponse response; + response.response = m_gui.popupRun(request.data.client, + PrivilegeInfo::getPrivilegeDisplayName(request.data.privilege)); - if (response.response == NResponseType::None) { - continue; - } + m_gui.delDismissFd(m_currentPeerSocket.getFd()); - if (!sendResponse(response)) { - ALOGE("Couldn't send response, closing..."); - break; - } + response.id = request.id; + if (response.response == NResponseType::None) { + return; + } - int ack = 0; - if (!m_clientSocket.recv(ack)) { - ALOGI("Askuserd closed connection, closing..."); - break; - } + if (!sendResponse(response)) { + ALOGE("Couldn't send response, closing..."); + return; + } + + switch (response.response) { + case NResponseType::Error: + ALOGE("Error in user interface : " << m_gui.getErrorMsg()); + break; + case NResponseType::Allow: + case NResponseType::Never: + setSecurityLevel(request.data.client, request.data.privilege, + Translator::Gui::responseToString(response.response)); + break; + case NResponseType::Deny: + case NResponseType::None: + break; + default: + ALOGW("Unknown response type returned"); + break; + } - if (ack != Protocol::ackCode) - throw Exception("Incorrect ack"); + return; +} - switch (response.response) { - case NResponseType::Error: - throw Exception(m_gui->getErrorMsg()); - case NResponseType::Allow: - case NResponseType::Never: - setSecurityLevel(request.data.client, request.data.privilege, - Translator::Gui::responseToString(response.response)); - break; - default: - ALOGD("Unknown response type returned"); - break; - } +void AskUserTalker::activateCurrentClient() { + ALOGD("Activating current peer : " << m_currentPeerSocket.getFd()); + m_poller.setEvents(m_currentPeerSocket.getFd(), POLLIN | POLLHUP | POLLERR); +} +void AskUserTalker::deactivateCurrentClient() { + ALOGD("Deactivating current peer : " << m_currentPeerSocket.getFd()); + m_poller.unset(m_currentPeerSocket.getFd()); +} + +void AskUserTalker::switchToNextClient() { + deactivateCurrentClient(); + m_currentPeerSocket.close(); + if (m_pendingPeers.empty()) { + ALOGD("No pending peers"); + return; } + m_currentPeerSocket = std::move(m_pendingPeers.front()); + m_pendingPeers.pop_front(); + activateCurrentClient(); + ALOGD("Setting current peer : " << m_currentPeerSocket.getFd()); } -void AskUserTalker::stop() -{ - m_gui->stop(); - m_clientSocket.close(); +void AskUserTalker::addNewClient(Socket &&newPeer) { + if (m_currentPeerSocket.getFd() == -1) { + ALOGD("Setting current peer : " << newPeer.getFd()); + m_currentPeerSocket = std::move(newPeer); + activateCurrentClient(); + } else { + m_pendingPeers.emplace_back(std::move(newPeer)); + ALOGD("Pushing peer to queue : " << newPeer.getFd()); + } } -bool AskUserTalker::shouldDismiss() +void AskUserTalker::run() { - Poll poller(1); - poller.setEvents(sockfd, POLLIN); - int ret = poller.wait(0); - if (ret == 0) - return false; - if (ret == -1) { - ALOGE("Poll failed"); - return true; - } - int a = 0x00; - m_clientSocket.recv(a); + m_running = true; + m_gui.addDismissFd(m_signalSocket.getFd(), AskUserTalker::dissmissCb, this); + while(m_running) { + int ret = m_poller.wait(-1); + if (ret == -1) { + ALOGE_ERRNO("Poll failed: "); + break; + } + if (ret == 0) { + ALOGD("Strange, poll timeouted..."); + continue; + } - if (a != Protocol::dissmisCode) - throw Exception("Incorrect dismiss flag"); + ALOGD("Poll returned " << ret << " events"); + // signal fd + if (m_poller.getEvents(m_signalSocket.getFd()) & POLLIN) { + signalfd_siginfo si; + if (!m_signalSocket.recv(si)) { + ALOGE_ERRNO("Reading signal info failed"); + break; + } + if (si.ssi_signo == SIGTERM) { + ALOGD("Got signal to exit, closing..."); + break; + } else { + ALOGW("Unknown signal caught, ignoring..."); + } + } + // listen fd + if (m_poller.getEvents(m_serverSocket.getFd()) & POLLIN) { + ALOGD("New peer connected"); + Socket newPeer = std::move(m_serverSocket.accept()); + if (newPeer.getFd() == -1) { + throw ErrnoException("Failed to accept new peer"); + } + + addNewClient(std::move(newPeer)); + continue; + } + // client fd + if ((m_poller.getEvents(m_currentPeerSocket.getFd()) & POLLHUP) + || (m_poller.getEvents(m_currentPeerSocket.getFd()) & POLLERR)) { + LOGW("Peer disconnected or error"); + switchToNextClient(); + continue; + } + if (m_poller.getEvents(m_currentPeerSocket.getFd()) & POLLIN) { + // Handle client then switch to next accepted client + ALOGD("Fetching request from client"); + handlePeer(); + switchToNextClient(); + } + } + m_running = false; + stop(); +} - return true; +void AskUserTalker::stop() +{ + m_gui.delDismissFd(m_currentPeerSocket.getFd()); + m_gui.delDismissFd(m_signalSocket.getFd()); + m_gui.stop(); + m_currentPeerSocket.close(); + for (auto &peer: m_pendingPeers) { + peer.close(); + } + m_serverSocket.close(); } } /* namespace Notification */ diff --git a/src/agent/notification-daemon/AskUserTalker.h b/src/agent/notification-daemon/AskUserTalker.h index 1a53589..fc7c9f0 100644 --- a/src/agent/notification-daemon/AskUserTalker.h +++ b/src/agent/notification-daemon/AskUserTalker.h @@ -14,16 +14,19 @@ * limitations under the License */ /** - * @file src/notification-daemon/GuiRunner.h + * @file src/agent/notification-daemon/AskUserTalker.h * @author Oskar Świtalski + * @author Zofia Abramowska * @brief Declaration of AskUserTalker class */ #pragma once +#include #include "GuiRunner.h" +#include #include #include #include @@ -35,20 +38,30 @@ namespace Notification { class AskUserTalker { public: - AskUserTalker(GuiRunner *gui); + AskUserTalker(); + void init(); void run(); void stop(); - bool shouldDismiss(); - private: + static void dissmissCb(int fd, void *data); + void setSignalDescriptor(); + void activateCurrentClient(); + void deactivateCurrentClient(); + void addNewClient(Socket &&newPeer); + void switchToNextClient(); + void handlePeer(); bool fetchRequest(NotificationRequest &request); bool sendResponse(const NotificationResponse &response); - Socket m_clientSocket; - GuiRunner *m_gui; - int sockfd = 0; - bool stopFlag = false; + Poll m_poller; + Socket m_signalSocket; + Socket m_serverSocket; + Socket m_currentPeerSocket; + GuiRunner m_gui; + std::list m_pendingPeers; + bool m_dismissPopup = false; + bool m_running = false; }; } /* namespace Notification */ diff --git a/src/agent/notification-daemon/GuiRunner.cpp b/src/agent/notification-daemon/GuiRunner.cpp index a4b3f88..4783bc3 100644 --- a/src/agent/notification-daemon/GuiRunner.cpp +++ b/src/agent/notification-daemon/GuiRunner.cpp @@ -14,8 +14,9 @@ * limitations under the License */ /** - * @file src/notification-daemon/GuiRunner.cpp + * @file src/agent/notification-daemon/GuiRunner.cpp * @author Oskar Świtalski + * @author Zofia Abramowska * @brief Definition of GuiRunner class */ @@ -30,78 +31,102 @@ namespace AskUser { namespace Notification { -namespace { - -bool should_raise = false; - -void unfocused(void *data, Evas_Object *, void *) +void GuiRunner::unfocused(void *data, Evas_Object *, void *) { - if (data == NULL) - return; + GuiRunner *runner = static_cast(data); - PopupData *res = static_cast(data); - - if (should_raise) - elm_win_raise(res->win); + if (runner->m_shouldRaise) + elm_win_raise(runner->m_win); else elm_exit(); } -void inline win_close(Evas_Object *win) { - should_raise = false; - elm_win_lower(win); +void GuiRunner::winClose() +{ + ALOGD("Window close"); + m_shouldRaise = false; + elm_win_lower(m_win); } -void inline answer(void *data, NResponseType response) +void GuiRunner::answer(NResponseType response) { ALOGD("User selected: " + Translator::Gui::responseToString(response)); - if (data == NULL) - return; - - PopupData *res = static_cast(data); - res->type = response; - win_close(res->win); + m_popupResponse = response; + winClose(); } -void allow_answer(void *data, Evas_Object *, void *) +void GuiRunner::allowAnswerCb(void *data, Evas_Object *, void *) { - answer(data, NResponseType::Allow); + GuiRunner* runner = static_cast(data); + runner->answer(NResponseType::Allow); } -void deny_answer(void *data, Evas_Object *, void *) +void GuiRunner::denyAnswerCb(void *data, Evas_Object *, void *) { - answer(data, NResponseType::Deny); + GuiRunner* runner = static_cast(data); + runner->answer(NResponseType::Deny); } -void never_answer(void *data, Evas_Object *, void *) +void GuiRunner::neverAnswerCb(void *data, Evas_Object *, void *) { - answer(data, NResponseType::Never); + GuiRunner* runner = static_cast(data); + runner->answer(NResponseType::Never); } -Eina_Bool timeout_answer(void *data) { - if (!data) - return ECORE_CALLBACK_RENEW; +Eina_Bool GuiRunner::dismissFdCb(void *data, Ecore_Fd_Handler *handler) { + ALOGD("Dismiss fd awoken"); + GuiRunner *runner = static_cast(data); - drop *d = static_cast(data); - - if (d->handle()) { - win_close(d->popup->win); + int fd = ecore_main_fd_handler_fd_get(handler); + if (fd == -1) { + ALOGE("Failed to fetch fd from handler"); + return ECORE_CALLBACK_CANCEL; } - return ECORE_CALLBACK_RENEW; + ALOGD("Dismiss descriptor " << fd << " is active, closing window..."); + auto fdIt = runner->m_fdCbDataMap.find(fd); + if (fdIt == runner->m_fdCbDataMap.end()) + return ECORE_CALLBACK_CANCEL; + + auto cbData = fdIt->second; + cbData.userCb(fd, cbData.userData); + runner->m_fdCbDataMap.erase(fdIt); + + runner->winClose(); + return ECORE_CALLBACK_CANCEL; } -} /* namespace */ +GuiRunner::~GuiRunner() +{ + for (auto &fdCbData : m_fdCbDataMap) { + ecore_main_fd_handler_del(fdCbData.second.handler); + } +} -GuiRunner::GuiRunner() +void GuiRunner::delDismissFd(int fd) { - m_popupData = new PopupData({NResponseType::Deny, nullptr}); + auto fdIt = m_fdCbDataMap.find(fd); + if (fdIt == m_fdCbDataMap.end()) + return; + ecore_main_fd_handler_del(fdIt->second.handler); + m_fdCbDataMap.erase(fdIt); } -GuiRunner::~GuiRunner() +void GuiRunner::addDismissFd(int fd, DissmissCb cb, void *data) { - delete m_popupData; + delDismissFd(fd); + + auto handler = ecore_main_fd_handler_add(fd, + // Thank you efl for this ugly code + static_cast(ECORE_FD_READ | ECORE_FD_ERROR), + &GuiRunner::dismissFdCb, this, + nullptr, nullptr); + if (handler == nullptr) { + throw Exception("Couldn't set fd handler"); + } + + m_fdCbDataMap[fd] = CbData{cb, data, handler}; } void GuiRunner::initialize() @@ -110,23 +135,39 @@ void GuiRunner::initialize() //placeholder m_win = elm_win_add(NULL, dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_TITLE"), - ELM_WIN_DOCK); + ELM_WIN_DOCK); + if (!m_win) { + ALOGE("EFL : Failed to add window"); + throw Exception("Elementary failed"); + } elm_win_autodel_set(m_win, EINA_TRUE); elm_win_override_set(m_win, EINA_TRUE); elm_win_alpha_set(m_win, EINA_TRUE); // popup m_popup = elm_popup_add(m_win); + if (!m_popup) { + ALOGE("EFL : Failed to add popup"); + throw Exception("Elementary failed"); + } elm_object_part_text_set(m_popup, "title,text", dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_TITLE")); // box m_box = elm_box_add(m_popup); + if (!m_box) { + ALOGE("EFL : Failed to add box"); + throw Exception("Enlightement failed"); + } evas_object_size_hint_weight_set(m_box, EVAS_HINT_EXPAND, 0); evas_object_size_hint_align_set(m_box, EVAS_HINT_FILL, 0.0); // content m_content = elm_label_add(m_popup); + if (!m_content) { + ALOGE("EFL : Failed to add content"); + throw Exception("Enlightement failed"); + } elm_object_style_set(m_content, "elm.swallow.content"); elm_label_line_wrap_set(m_content, ELM_WRAP_MIXED); evas_object_size_hint_weight_set(m_content, EVAS_HINT_EXPAND, 0.0); @@ -138,44 +179,48 @@ void GuiRunner::initialize() // buttons m_allowButton = elm_button_add(m_popup); + if (!m_allowButton) { + ALOGE("EFL : Failed to add allow button"); + throw Exception("Enlightement failed"); + } elm_object_part_content_set(m_popup, "button1", m_allowButton); elm_object_text_set(m_allowButton, dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_BUTTON_ALLOW")); m_neverButton = elm_button_add(m_popup); + if (!m_neverButton) { + ALOGE("EFL : Failed to add never button"); + throw Exception("Enlightement failed"); + } elm_object_text_set(m_neverButton, dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_BUTTON_NEVER")); elm_object_part_content_set(m_popup, "button2", m_neverButton); m_denyButton = elm_button_add(m_popup); + if (!m_denyButton) { + ALOGE("EFL : Failed to add deny button"); + throw Exception("Enlightement failed"); + } elm_object_text_set(m_denyButton, dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_BUTTON_DENY")); elm_object_part_content_set(m_popup, "button3", m_denyButton); // callbacks - evas_object_smart_callback_add(m_win, "unfocused", unfocused, m_popupData); - evas_object_smart_callback_add(m_allowButton, "clicked", allow_answer, m_popupData); - evas_object_smart_callback_add(m_neverButton, "clicked", never_answer, m_popupData); - evas_object_smart_callback_add(m_denyButton, "clicked", deny_answer, m_popupData); + evas_object_smart_callback_add(m_win, "unfocused", &GuiRunner::unfocused, this); + evas_object_smart_callback_add(m_allowButton, "clicked", &GuiRunner::allowAnswerCb, this); + evas_object_smart_callback_add(m_neverButton, "clicked", &GuiRunner::neverAnswerCb, this); + evas_object_smart_callback_add(m_denyButton, "clicked", &GuiRunner::denyAnswerCb, this); - m_popupData->win = m_win; m_initialized = true; - } NResponseType GuiRunner::popupRun(const std::string &app, const std::string &perm) { - try { - if (!m_dropHandler) - throw Exception("DropHandler was not initialized"); - - if (!m_initialized) + if (!m_initialized) { initialize(); - + } m_running = true; - std::unique_ptr Drop(new drop({m_dropHandler, m_popupData})); - m_timer = ecore_timer_add(0.1, timeout_answer, Drop.get()); // create message char *messageFormat = dgettext(PROJECT_NAME, "SID_PRIVILEGE_REQUEST_DIALOG_MESSAGE"); @@ -187,9 +232,9 @@ NResponseType GuiRunner::popupRun(const std::string &app, const std::string &per if (ret < 0) throw ErrnoException("snprintf failed", errno); - m_popupData->type = NResponseType::None; + m_popupResponse = NResponseType::None; - should_raise = true; + m_shouldRaise = true; elm_object_text_set(m_content, buf); @@ -197,32 +242,24 @@ NResponseType GuiRunner::popupRun(const std::string &app, const std::string &per evas_object_show(m_win); elm_win_raise(m_win); + + ALOGD("Showing popup"); elm_run(); + ALOGD("Popup closed"); - ecore_timer_del(m_timer); m_running = false; - should_raise = false; + m_shouldRaise = false; } catch (const std::exception &e) { - m_popupData->type = NResponseType::Error; + m_popupResponse = NResponseType::Error; m_errorMsg = std::move(e.what()); } - return m_popupData->type; -} - -void GuiRunner::setDropHandler(DropHandler dropHandler) -{ - m_dropHandler = dropHandler; + return m_popupResponse; } void GuiRunner::stop() { - if (m_running) { - evas_object_hide(m_win); - elm_exit(); - } - elm_shutdown(); } } /* namespace Notification */ diff --git a/src/agent/notification-daemon/GuiRunner.h b/src/agent/notification-daemon/GuiRunner.h index 8d4c9df..613b7c4 100644 --- a/src/agent/notification-daemon/GuiRunner.h +++ b/src/agent/notification-daemon/GuiRunner.h @@ -14,8 +14,9 @@ * limitations under the License */ /** - * @file src/notification-daemon/GuiRunner.h + * @file src/agent/notification-daemon/GuiRunner.h * @author Oskar Świtalski + * @author Zofia Abramowska * @brief Declaration of GuiRunner class */ @@ -23,6 +24,7 @@ #include #include +#include #include #include @@ -32,49 +34,53 @@ namespace AskUser { namespace Notification { -typedef std::function DropHandler; - -struct PopupData { - NResponseType type; - Evas_Object *win; -}; - -struct drop { - DropHandler handle; - PopupData *popup; -}; - class GuiRunner { public: - GuiRunner(); + typedef std::function DissmissCb; + + GuiRunner() = default; + void initialize(); + void addDismissFd(int fd, DissmissCb cb, void *data); + void delDismissFd(int fd); ~GuiRunner(); NResponseType popupRun(const std::string &app, const std::string &perm); - - void setDropHandler(DropHandler dropHandler); void stop(); std::string getErrorMsg() { return m_errorMsg; } private: - PopupData *m_popupData; - DropHandler m_dropHandler; - - Evas_Object *m_win; - Evas_Object *m_popup; - Evas_Object *m_box; - Evas_Object *m_content; - Evas_Object *m_allowButton; - Evas_Object *m_neverButton; - Evas_Object *m_denyButton; - Ecore_Timer *m_timer; + static Eina_Bool dismissFdCb(void *data, Ecore_Fd_Handler *handler); + static void unfocused(void *data, Evas_Object *, void *); + static void allowAnswerCb(void *data, Evas_Object *, void *); + static void denyAnswerCb(void *data, Evas_Object *, void *); + static void neverAnswerCb(void *data, Evas_Object *, void *); + + void answer(NResponseType response); + void winClose(); + + struct CbData { + DissmissCb userCb; + void *userData; + Ecore_Fd_Handler *handler; + }; + + std::map m_fdCbDataMap; + NResponseType m_popupResponse = NResponseType::Error; + + Evas_Object *m_win = nullptr; + Evas_Object *m_popup = nullptr; + Evas_Object *m_box = nullptr; + Evas_Object *m_content = nullptr; + Evas_Object *m_allowButton = nullptr; + Evas_Object *m_neverButton = nullptr; + Evas_Object *m_denyButton = nullptr; bool m_running = false; bool m_initialized = false; + bool m_shouldRaise = false; std::string m_errorMsg; - - void initialize(); }; } /* namespace Notification */ diff --git a/src/agent/notification-daemon/main.cpp b/src/agent/notification-daemon/main.cpp index 3d0a46e..295f208 100644 --- a/src/agent/notification-daemon/main.cpp +++ b/src/agent/notification-daemon/main.cpp @@ -47,6 +47,8 @@ int main() try { GuiRunner gui; AskUserTalker askUserTalker(&gui); +// AskUserTalker askUserTalker; + askUserTalker.init(); #ifdef BUILD_WITH_SYSTEMD_DAEMON int ret = sd_notify(0, "READY=1"); @@ -58,7 +60,6 @@ int main() #endif askUserTalker.run(); - } catch (std::exception &e) { ALOGE("Askuser-notification stopped because of: <" << e.what() << ">."); } catch (...) { diff --git a/src/common/socket/Socket.cpp b/src/common/socket/Socket.cpp index 4d32376..bbae192 100644 --- a/src/common/socket/Socket.cpp +++ b/src/common/socket/Socket.cpp @@ -48,7 +48,21 @@ Socket &Socket::operator=(Socket &&other) { return *this; } +void Socket::setFd(int fd) { + // Setting fd can only happen for non initialized sockets + if ( m_fd != -1) { + ALOGW("Socket already initialized"); + return; + } + m_fd = fd; +} + bool Socket::connect(const std::string &path) { + if (m_fd != -1) { + ALOGW("Socket already initialized"); + return false; + } + if (m_type != PeerType::CLIENT) { ALOGW("Connect is available only for CLIENT type socket"); return false; @@ -81,6 +95,11 @@ bool Socket::connect(const std::string &path) { } bool Socket::bindAndListen(const std::string &path) { + if (m_fd != -1) { + ALOGW("Socket already initialized"); + return false; + } + if (m_type != PeerType::SERVER) { ALOGW("Connect is available only for SERVER type socket"); return false; @@ -132,7 +151,7 @@ Socket Socket::accept() { int retFd = TEMP_FAILURE_RETRY(::accept(m_fd, nullptr, nullptr)); if (retFd < 0) { ALOGE_ERRNO("accept failed"); - return -1; + return Socket(-1); } ALOGD("Accepted socket <" << retFd << ">"); return Socket(retFd); @@ -183,7 +202,21 @@ bool Socket::recv(int &msg) { return true; } +bool Socket::recv(signalfd_siginfo &info) { + struct signalfd_siginfo si; + + if (!recvData(&si, sizeof(si))) { + return false; + } + info = si; + return true; +} + bool Socket::sendData(const void *data, size_t len) { + if (m_type == PeerType::SIGNAL) { + ALOGW("Illegal usage of signal type socket"); + return false; + } int result = 0; size_t bytesSend = 0; @@ -217,6 +250,7 @@ bool Socket::send(int msg) { void Socket::close() { ::close(m_fd); + m_fd = -1; } } /* namespace AskUser */ diff --git a/src/common/socket/Socket.h b/src/common/socket/Socket.h index db5a68a..c302bdf 100644 --- a/src/common/socket/Socket.h +++ b/src/common/socket/Socket.h @@ -24,6 +24,7 @@ #include #include +#include namespace AskUser { @@ -32,12 +33,13 @@ public: enum PeerType { CLIENT, // connect SERVER, // accept - PEER // accepted peer + PEER, // accepted peer + SIGNAL // for signalfd }; Socket(PeerType type) : m_type(type), m_fd(-1) {} - Socket(int fd) : m_type(PEER), m_fd(fd) {} + Socket(int fd, PeerType type = PEER) : m_type(type), m_fd(fd) {} Socket(const Socket &other) = delete; Socket &operator=(const Socket &other) = delete; @@ -47,6 +49,7 @@ public: ~Socket() { ::close(m_fd); } + void setFd(int fd); int getFd() const { return m_fd; } bool connect(const std::string &path); @@ -56,6 +59,7 @@ public: bool recv(std::string &msg); bool recv(int &msg); + bool recv(signalfd_siginfo &info); bool send(const std::string &msg); bool send(int msg); -- 2.7.4