From badd67e83d8fe0de6b36f9364473d3b85663e9e1 Mon Sep 17 00:00:00 2001
From: Piotr Sawicki
Date: Wed, 31 Jan 2018 11:51:07 +0100
Subject: [PATCH] Let client create one connection per one request
Change-Id: I220c399d125f3de70490855c3c4fe08a2958b3eb
---
src/capi/impl/privacy_privilege_manager.c | 114 ++++++++++++++-----------
src/client/api/ApiInterface.h | 8 +-
src/client/api/askuser-notification-client.cpp | 6 +-
src/client/impl/ApiInterfaceImpl.cpp | 81 +++++++++++-------
src/client/impl/ApiInterfaceImpl.h | 22 +++--
src/client/impl/PopupCallbackClosure.h | 59 -------------
src/ipc/client-channel.cpp | 20 +++--
src/ipc/client-channel.h | 6 +-
src/ipc/common-types.h | 7 +-
9 files changed, 153 insertions(+), 170 deletions(-)
delete mode 100644 src/client/impl/PopupCallbackClosure.h
diff --git a/src/capi/impl/privacy_privilege_manager.c b/src/capi/impl/privacy_privilege_manager.c
index 98eed15..a009208 100644
--- a/src/capi/impl/privacy_privilege_manager.c
+++ b/src/capi/impl/privacy_privilege_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,12 +28,17 @@
#define UNUSED __attribute__((unused))
-struct ppm_private_s {
- askuser_client *client;
+struct ppm_channel_s {
GIOChannel *channel;
GIOCondition condition;
guint watch_id;
};
+typedef struct ppm_channel_s ppm_channel;
+
+struct ppm_private_s {
+ askuser_client *client;
+ GHashTable *channels;
+};
typedef struct ppm_private_s ppm_private;
struct ppm_callback_closure_s {
@@ -44,40 +49,37 @@ typedef struct ppm_callback_closure_s ppm_callback_closure;
static ppm_private *ppm_handle = NULL;
-static void ppm_private_init(ppm_private *handle)
+static void ppm_free_channel(gpointer data)
{
- handle->channel = NULL;
- handle->condition = 0;
- handle->watch_id = 0;
+ ppm_channel* channel = data;
+
+ if (channel) {
+ g_source_remove(channel->watch_id);
+ g_io_channel_unref(channel->channel);
+ g_free(channel);
+ }
}
static ppm_error_e ask_user_to_ppm_error(int ask_error)
{
- ppm_error_e ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
-
switch (ask_error) {
case ASKUSER_API_SUCCESS:
- ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
- break;
+ return PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
case ASKUSER_API_UNKNOWN_ERROR:
- ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN;
- break;
+ return PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN;
case ASKUSER_API_OUT_OF_MEMORY:
- ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY;
- break;
+ return PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY;
case ASKUSER_API_INVALID_PARAM:
- ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER;
- break;
+ return PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER;
case ASKUSER_API_CONNECTION_ERROR:
- ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_IO_ERROR;
- break;
+ return PRIVACY_PRIVILEGE_MANAGER_ERROR_IO_ERROR;
case ASKUSER_API_ALREADY_IN_PROGRESS:
- ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_ALREADY_IN_PROGRESS;
+ return PRIVACY_PRIVILEGE_MANAGER_ERROR_ALREADY_IN_PROGRESS;
default:
break;
}
- return ret;
+ return PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
}
static ppm_check_result_e ask_user_check_result_to_ppm(askuser_check_result result)
@@ -98,7 +100,7 @@ static ppm_request_result_e askuser_client_request_result_to_ppm(askuser_popup_r
{
switch (result) {
case ASKUSER_POPUP_RESULT_ALLOW_FOREVER:
- return PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_ALLOW_FOREVER;
+ return PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_ALLOW_FOREVER;
case ASKUSER_POPUP_RESULT_DENY_FOREVER:
return PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_DENY_FOREVER;
case ASKUSER_POPUP_RESULT_DENY_ONCE:
@@ -138,11 +140,6 @@ static gboolean ppm_error_condition(GIOCondition cond)
return !!(cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL));
}
-static gboolean ppm_is_connected(ppm_private *handle)
-{
- return handle->channel != NULL;
-}
-
static gboolean ppm_gio_cb(GIOChannel *src, GIOCondition cond, gpointer data)
{
int fd, events;
@@ -163,33 +160,38 @@ static void ask_status_callback(int fd, int events, void *p_user_data)
GIOCondition gio_condition = askuser_events_to_g_io_condition(events);
if (events == ASKUSER_EMPTY_EVENTS) {
- if (ppm_is_connected(handle)) {
- g_source_remove(handle->watch_id);
- g_io_channel_unref(handle->channel);
- ppm_private_init(handle);
- }
+ g_hash_table_remove(handle->channels, GINT_TO_POINTER(fd));
return;
}
- if (!ppm_is_connected(handle)) {
- handle->condition = gio_condition;
- handle->channel = g_io_channel_unix_new(fd);
+ ppm_channel *channel = g_hash_table_lookup(handle->channels, GINT_TO_POINTER(fd));
+
+ if (channel == NULL) {
+ channel = (ppm_channel *) g_malloc0(sizeof(ppm_channel));
+ if (!channel) {
+ return;
+ }
+
+ channel->condition = gio_condition;
+ channel->channel = g_io_channel_unix_new(fd);
- g_io_channel_set_encoding (handle->channel, NULL, NULL);
- g_io_channel_set_close_on_unref(handle->channel, FALSE);
+ g_io_channel_set_encoding (channel->channel, NULL, NULL);
+ g_io_channel_set_close_on_unref(channel->channel, FALSE);
- handle->watch_id = g_io_add_watch(handle->channel,
- handle->condition | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ channel->watch_id = g_io_add_watch(channel->channel,
+ channel->condition | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
ppm_gio_cb,
handle);
+
+ g_hash_table_insert(handle->channels, GINT_TO_POINTER(fd), (gpointer) channel);
return;
}
- if (handle->condition != gio_condition) {
- handle->condition = gio_condition;
- g_source_remove(handle->watch_id);
- handle->watch_id = g_io_add_watch(handle->channel,
- handle->condition | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ if (channel->condition != gio_condition) {
+ channel->condition = gio_condition;
+ g_source_remove(channel->watch_id);
+ channel->watch_id = g_io_add_watch(channel->channel,
+ channel->condition | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
ppm_gio_cb,
handle);
}
@@ -220,7 +222,14 @@ static void ppm_popup_response_callback(UNUSED int request_id, askuser_call_caus
static void ppm_free_client()
{
if (ppm_handle != NULL) {
- askuser_client_finalize(ppm_handle->client);
+ if (ppm_handle->client != NULL) {
+ askuser_client_finalize(ppm_handle->client);
+ }
+
+ if (ppm_handle->channels != NULL) {
+ g_hash_table_destroy(ppm_handle->channels);
+ }
+
free(ppm_handle);
ppm_handle = NULL;
}
@@ -234,20 +243,23 @@ static int ppm_init_client()
return PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY;
}
- ppm_private_init(ppm_handle);
+ ppm_handle->channels = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, ppm_free_channel);
+
+ if (ppm_handle->channels == NULL) {
+ ppm_free_client();
+ return PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY;
+ }
int ret = askuser_client_initialize(&ppm_handle->client, ask_status_callback, ppm_handle);
if (ret != ASKUSER_API_SUCCESS) {
- free(ppm_handle);
- ppm_handle = NULL;
+ ppm_free_client();
return ask_user_to_ppm_error(ret);
}
ret = atexit(ppm_free_client);
if (ret != 0) {
- askuser_client_finalize(ppm_handle->client);
- free(ppm_handle);
- ppm_handle = NULL;
+ ppm_free_client();
return PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN;
}
}
diff --git a/src/client/api/ApiInterface.h b/src/client/api/ApiInterface.h
index 87bb603..c1b5d2c 100644
--- a/src/client/api/ApiInterface.h
+++ b/src/client/api/ApiInterface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@
#include
-#include
#include
namespace AskUser {
@@ -40,8 +39,9 @@ public:
virtual int process(int fd, int events) = 0;
virtual askuser_check_result checkPrivilege(const std::string &privilege) = 0;
- virtual RequestId popupRequest(const PopupCallbackClosure &closure,
- const std::string &privilege) = 0;
+ virtual RequestId popupRequest(const std::string &privilege,
+ const askuser_popup_response_callback callback,
+ void *userData) = 0;
virtual bool popupRequestInProgress(const std::string &privilege) const = 0;
};
diff --git a/src/client/api/askuser-notification-client.cpp b/src/client/api/askuser-notification-client.cpp
index 7faa1f2..1067816 100644
--- a/src/client/api/askuser-notification-client.cpp
+++ b/src/client/api/askuser-notification-client.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@
#include
#include
-#include
#include
#include
@@ -129,8 +128,7 @@ int askuser_client_popup_request(askuser_client *p_client, const char *privilege
return ASKUSER_API_ALREADY_IN_PROGRESS;
}
- AskUser::Client::PopupCallbackClosure closure(response_callback, privilege, p_user_data);
- AskUser::Client::RequestId id = p_client->impl->popupRequest(closure, privilege);
+ AskUser::Client::RequestId id = p_client->impl->popupRequest(privilege, response_callback, p_user_data);
if (p_request_id) {
*p_request_id = id;
diff --git a/src/client/impl/ApiInterfaceImpl.cpp b/src/client/impl/ApiInterfaceImpl.cpp
index a1833e8..79619a2 100644
--- a/src/client/impl/ApiInterfaceImpl.cpp
+++ b/src/client/impl/ApiInterfaceImpl.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
* @brief The definition of ApiInterfaceImpl.
*/
+#include
#include
#include
@@ -121,73 +122,91 @@ askuser_check_result ApiInterfaceImpl::checkPrivilege(const std::string &privile
return ASKUSER_CHECK_RESULT_DENY;
}
-RequestId ApiInterfaceImpl::popupRequest(const PopupCallbackClosure &closure,
- const std::string &privilege)
+RequestId ApiInterfaceImpl::popupRequest(const std::string &privilege,
+ const askuser_popup_response_callback callback,
+ void *userData)
{
- RequestId id = static_cast(m_channel->popupRequest(privilege));
+ Protocol::ConnectionContext conCtx = m_channel->popupRequest(privilege);
- auto it = m_popupClosures.find(id);
- if (it != m_popupClosures.end()) {
- ALOGE("Popup closure exists for id: " << id <<
- " privilege: " << it->second.privilege() << ", replacing");
- popupResponse(id, ASKUSER_UNKNOWN_ERROR);
+ auto sameRequest = [&] (const Request &req) {
+ return req.m_requestId == conCtx.m_requestId;
+ };
+
+ auto reqIt = std::find_if(m_requests.begin(), m_requests.end(), sameRequest);
+ if (reqIt != m_requests.end()) {
+ ALOGE("Popup closure exists for id: " << conCtx.m_requestId <<
+ " privilege: " << reqIt->m_privilege << ", replacing");
+ popupResponse(conCtx.m_requestId, ASKUSER_UNKNOWN_ERROR);
}
if (popupRequestInProgress(privilege)) {
- ALOGE("Privilege " << closure.privilege() << " already exists in the pending privileges set");
+ ALOGE("Privilege " << privilege << " already exists in the pending requests");
}
- m_requestedPrivileges.insert(privilege);
- m_popupClosures.insert({id, closure});
+ m_requests.push_back({ conCtx.m_requestId, conCtx.m_fd, privilege, callback, userData });
- return id;
+ return conCtx.m_requestId;
}
bool ApiInterfaceImpl::popupRequestInProgress(const std::string &privilege) const
{
- return m_requestedPrivileges.find(privilege) != m_requestedPrivileges.end();
+ auto samePrivilege = [&] (const Request &req) {
+ return req.m_privilege == privilege;
+ };
+
+ return std::find_if(m_requests.begin(), m_requests.end(), samePrivilege) != m_requests.end();
}
void ApiInterfaceImpl::updateConnection(Protocol::ConnectionFd fd, int mask)
{
m_statusClosure(fd, askUserMaskToEvents(mask));
- // the connection is about to close, respond to all pending requests
if (mask == ASKUSER_EMPTY_EVENTS) {
- respondToAllRequests(ASKUSER_CALL_CAUSE_ERROR, ASKUSER_POPUP_RESULT_DENY_ONCE);
+ auto sameFd = [&] (const Request &req) {
+ return req.m_fd == fd;
+ };
+
+ auto reqIt = std::find_if(m_requests.begin(), m_requests.end(), sameFd);
+ if (reqIt == m_requests.end()) {
+ return;
+ }
+
+ ALOGW("askuser-notification has been unexpectedly stopped, "
+ "sending the error response for privilege: "
+ << reqIt->m_privilege << " id: " << reqIt->m_requestId);
+
+ popupResponse(reqIt->m_requestId, ASKUSER_UNKNOWN_ERROR);
}
}
void ApiInterfaceImpl::popupResponse(Protocol::RequestId id, int response)
{
- auto it = m_popupClosures.find(id);
- if (it == m_popupClosures.end()) {
- ALOGE("Couldn't find popup callback closure for id: " << id);
- return;
- }
+ auto sameRequestId = [&] (const Request &req) {
+ return req.m_requestId == id;
+ };
- const auto &closure = it->second;
- if (!popupRequestInProgress(closure.privilege())) {
- ALOGE("Couldn't find privilege " << closure.privilege() << " in the pending privileges set");
+ auto reqIt = std::find_if(m_requests.begin(), m_requests.end(), sameRequestId);
+ if (reqIt == m_requests.end()) {
+ ALOGE("Couldn't find request for id: " << id);
+ return;
}
askuser_call_cause cause = deduceCauseFromResponse(response);
askuser_popup_result res = responseToAskUserPopupResult(response);
- closure(id, cause, res);
+ reqIt->m_callback(id, cause, res, reqIt->m_privilege.c_str(), reqIt->m_userData);
- m_requestedPrivileges.erase(closure.privilege());
- m_popupClosures.erase(it);
+ m_requests.erase(reqIt);
}
void ApiInterfaceImpl::respondToAllRequests(askuser_call_cause cause, askuser_popup_result result)
{
- for (const auto &closure : m_popupClosures) {
- closure.second(closure.first, cause, result);
+ for (const auto &req : m_requests) {
+ req.m_callback(req.m_requestId, cause, result,
+ req.m_privilege.c_str(), req.m_userData);
}
- m_requestedPrivileges.clear();
- m_popupClosures.clear();
+ m_requests.clear();
}
} // namespace Client
diff --git a/src/client/impl/ApiInterfaceImpl.h b/src/client/impl/ApiInterfaceImpl.h
index efa97c6..40e8d48 100644
--- a/src/client/impl/ApiInterfaceImpl.h
+++ b/src/client/impl/ApiInterfaceImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,12 +22,10 @@
#pragma once
-#include