From: Piotr Sawicki
Date: Wed, 5 Jul 2017 11:30:43 +0000 (+0200)
Subject: Implement client side asynchronous channel
X-Git-Tag: submit/tizen/20170727.154157~1^2~41
X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bae242841bf973b5b672a9c33918b14f8ef4b13c;p=platform%2Fcore%2Fsecurity%2Faskuser.git
Implement client side asynchronous channel
* Implement an abstract channel and async client/server channels
* Adjust other modules to this new changes
Change-Id: I6788d01a220dfba3eb3ad2226a8a9ee96878153b
---
diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt
index 3fafb9f..271273c 100644
--- a/src/client/CMakeLists.txt
+++ b/src/client/CMakeLists.txt
@@ -26,6 +26,7 @@ PKG_CHECK_MODULES(ASKUSER_NOTIFICATION_CLIENT_DEP
INCLUDE_DIRECTORIES(SYSTEM ${ASKUSER_NOTIFICATION_CLIENT_DEP_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(
${ASKUSER_PATH}/common
+ ${ASKUSER_PATH}/ipc-lib
${ASKUSER_NOTIFICATION_CLIENT_PATH}/api
${ASKUSER_NOTIFICATION_CLIENT_PATH}/impl
${ASKUSER_NOTIFICATION_CLIENT_PATH}/include
@@ -34,6 +35,7 @@ INCLUDE_DIRECTORIES(
SET(ASKUSER_NOTIFICATION_CLIENT_SOURCES
${ASKUSER_NOTIFICATION_CLIENT_PATH}/api/askuser-notification-client.cpp
${ASKUSER_NOTIFICATION_CLIENT_PATH}/impl/ApiInterfaceImpl.cpp
+ ${ASKUSER_NOTIFICATION_CLIENT_PATH}/impl/ClientCallbacks.cpp
)
ADD_LIBRARY(
diff --git a/src/client/impl/ApiInterfaceImpl.cpp b/src/client/impl/ApiInterfaceImpl.cpp
index ce90206..1a3ec91 100644
--- a/src/client/impl/ApiInterfaceImpl.cpp
+++ b/src/client/impl/ApiInterfaceImpl.cpp
@@ -21,33 +21,68 @@
* @brief The definition of ApiInterfaceImpl.
*/
+#include
+#include
+
+#include "ClientCallbacks.h"
#include "ApiInterfaceImpl.h"
+namespace {
+
+int eventsToAskUserMask(int events)
+{
+ return ((events & ASKUSER_READ_EVENT) ? AskUser::Protocol::FdMask::READ : 0) |
+ ((events & ASKUSER_WRITE_EVENT) ? AskUser::Protocol::FdMask::WRITE : 0);
+}
+
+int askUserMaskToEvents(int mask)
+{
+ return ((AskUser::Protocol::FdMask::READ & mask) ? ASKUSER_READ_EVENT : 0) |
+ ((AskUser::Protocol::FdMask::WRITE & mask) ? ASKUSER_WRITE_EVENT : 0);
+}
+
+askuser_popup_result responseToAskUserPopupResult(int response)
+{
+ switch (response) {
+ case ASKUSER_ALLOW_FOREVER:
+ return ASKUSER_POPUP_RESULT_ALLOW_FOREVER;
+ case ASKUSER_DENY_FOREVER:
+ return ASKUSER_POPUP_RESULT_DENY_FOREVER;
+ case ASKUSER_DENY_ONCE:
+ return ASKUSER_POPUP_RESULT_DENY_ONCE;
+ }
+
+ return ASKUSER_POPUP_RESULT_DENY_ONCE;
+}
+
+} // namespace
+
namespace AskUser {
namespace Client {
ApiInterfaceImpl::ApiInterfaceImpl(const StatusCallbackClosure &statusClosure)
: m_statusClosure(statusClosure)
+, m_channel(std::move(Protocol::ClientCallbacksPtr(new ClientCallbacks(this))))
{
}
ApiInterfaceImpl::~ApiInterfaceImpl()
{
- // TODO
+ for (const auto &closure : m_callbacks) {
+ closure.second(closure.first, askuser_call_cause::ASKUSER_CALL_CAUSE_FINALIZE,
+ askuser_popup_result::ASKUSER_POPUP_RESULT_DENY_ONCE);
+ }
}
int ApiInterfaceImpl::process(int fd, int events)
{
- // TODO
- (void) fd;
- (void) events;
- return 0;
+ return m_channel.process(fd, eventsToAskUserMask(events));
}
askuser_check_result ApiInterfaceImpl::checkPrivilege(const std::string &privilege)
{
- // TODO
+ // TODO use PolicyFetchRequest
(void) privilege;
return ASKUSER_CHECK_RESULT_DENY;
@@ -56,11 +91,48 @@ askuser_check_result ApiInterfaceImpl::checkPrivilege(const std::string &privile
RequestId ApiInterfaceImpl::popupRequest(const PopupCallbackClosure &closure,
const std::string &privilege)
{
- // TODO
- (void) closure;
- (void) privilege;
+ Client::RequestId id = static_cast(m_channel.popupRequest(privilege));
+
+ auto it = m_callbacks.find(id);
+ if (it != m_callbacks.end()) {
+ it->second(it->first, ASKUSER_CALL_CAUSE_ERROR, ASKUSER_POPUP_RESULT_DENY_ONCE);
+ m_callbacks.erase(it);
+ }
+
+ m_callbacks.insert({id, closure});
+
+ return id;
+}
+
+void ApiInterfaceImpl::updateConnection(Protocol::ConnectionFd fd, int mask)
+{
+ m_statusClosure(fd, askUserMaskToEvents(mask));
+
+ // remove all pending events
+ if (mask == ASKUSER_EMPTY_EVENTS) {
+ for (const auto &closure : m_callbacks) {
+ closure.second(closure.first, ASKUSER_CALL_CAUSE_ERROR, ASKUSER_POPUP_RESULT_DENY_ONCE);
+ }
+
+ m_callbacks.clear();
+ }
+}
+
+void ApiInterfaceImpl::popupResponse(Protocol::RequestId id, int response)
+{
+ auto it = m_callbacks.find(id);
+ if (it == m_callbacks.end()) {
+ return;
+ }
+
+ askuser_call_cause cause = ASKUSER_CALL_CAUSE_ANSWER;
+ if (response == ASKUSER_UNKNOWN_ERROR) {
+ cause = ASKUSER_CALL_CAUSE_ERROR;
+ }
- return 0;
+ askuser_popup_result res = responseToAskUserPopupResult(response);
+ it->second(id, cause, res);
+ m_callbacks.erase(it);
}
} // namespace Client
diff --git a/src/client/impl/ApiInterfaceImpl.h b/src/client/impl/ApiInterfaceImpl.h
index e255ac2..0b45410 100644
--- a/src/client/impl/ApiInterfaceImpl.h
+++ b/src/client/impl/ApiInterfaceImpl.h
@@ -23,19 +23,23 @@
#pragma once
+#include
+
#include
#include
#include
+#include
+
#include
namespace AskUser {
namespace Client {
-class ApiInterfaceImpl : public AskUser::Client::ApiInterface {
+class ApiInterfaceImpl : public ApiInterface {
public:
- ApiInterfaceImpl(const AskUser::Client::StatusCallbackClosure &closure);
+ ApiInterfaceImpl(const StatusCallbackClosure &closure);
ApiInterfaceImpl(const ApiInterfaceImpl& orig) = delete;
virtual ~ApiInterfaceImpl();
@@ -43,11 +47,16 @@ public:
virtual int process(int fd, int events);
virtual askuser_check_result checkPrivilege(const std::string &privilege);
- virtual RequestId popupRequest(const AskUser::Client::PopupCallbackClosure &closure,
+ virtual RequestId popupRequest(const PopupCallbackClosure &closure,
const std::string &privilege);
+ void updateConnection(Protocol::ConnectionFd fd, int mask);
+ void popupResponse(Protocol::RequestId id, int response);
+
private:
- AskUser::Client::StatusCallbackClosure m_statusClosure;
+ StatusCallbackClosure m_statusClosure;
+ Protocol::ClientChannel m_channel;
+ std::map m_callbacks;
};
} // namespace Client
diff --git a/src/client/impl/ClientCallbacks.cpp b/src/client/impl/ClientCallbacks.cpp
new file mode 100644
index 0000000..84705d4
--- /dev/null
+++ b/src/client/impl/ClientCallbacks.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 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.
+ * 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
+ */
+
+/**
+ * @file ClientCallbacks.cpp
+ * @author Piotr Sawicki
+ * @version 1.0
+ * @brief The definition of ClientCallbacks.
+ */
+
+#include "ClientCallbacks.h"
+
+namespace AskUser {
+
+namespace Client {
+
+void ClientCallbacks::updateConnection(Protocol::ConnectionFd fd, int mask)
+{
+ m_api->updateConnection(fd, mask);
+}
+
+void ClientCallbacks::popupResponse(Protocol::RequestId id, int response)
+{
+ m_api->popupResponse(id, response);
+}
+
+} // namespace Client
+
+} // namespace AskUser
diff --git a/src/client/impl/ClientCallbacks.h b/src/client/impl/ClientCallbacks.h
new file mode 100644
index 0000000..440bde1
--- /dev/null
+++ b/src/client/impl/ClientCallbacks.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017 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.
+ * 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
+ */
+
+/**
+ * @file ClientCallbacks.h
+ * @author Piotr Sawicki
+ * @version 1.0
+ * @brief The declaration of ClientCallbacks.
+ */
+
+#pragma once
+
+#include
+
+#include "ApiInterfaceImpl.h"
+
+namespace AskUser {
+
+namespace Client {
+
+class ClientCallbacks : public Protocol::IClientCallbacks {
+public:
+
+ ClientCallbacks(ApiInterfaceImpl *api) : m_api(api)
+ {}
+
+ virtual void updateConnection(Protocol::ConnectionFd fd, int mask);
+ virtual void popupResponse(Protocol::RequestId id, int response);
+
+private:
+ ApiInterfaceImpl *m_api;
+};
+
+} // namespace Client
+
+} // namespace AskUser
diff --git a/src/ipc-lib/CMakeLists.txt b/src/ipc-lib/CMakeLists.txt
index 7a14619..78899a4 100644
--- a/src/ipc-lib/CMakeLists.txt
+++ b/src/ipc-lib/CMakeLists.txt
@@ -25,12 +25,14 @@ PKG_CHECK_MODULES(ASKUSER_NOTIFICATION_LIB_DEP
INCLUDE_DIRECTORIES(SYSTEM ${ASKUSER_NOTIFICATION_LIB_DEP_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(
+ ${ASKUSER_PATH}/common
${ASKUSER_NOTIFICATION_LIB_PATH}
)
SET(ASKUSER_NOTIFICATION_LIB_SOURCES
${ASKUSER_NOTIFICATION_LIB_PATH}/ask-user-channel.cpp
${ASKUSER_NOTIFICATION_LIB_PATH}/ask-user-client-channel.cpp
+ ${ASKUSER_NOTIFICATION_LIB_PATH}/ask-user-server-channel.cpp
${ASKUSER_NOTIFICATION_LIB_PATH}/sock.cpp
${ASKUSER_NOTIFICATION_LIB_PATH}/ask-user-config.cpp
)
@@ -53,7 +55,12 @@ SET_TARGET_PROPERTIES(${TARGET_ASKUSER_NOTIFICATION_LIB}
LINK_DIRECTORIES(${ASKUSER_NOTIFICATION_LIB_DEP_LIBRARY_DIRS})
-TARGET_LINK_LIBRARIES(${TARGET_ASKUSER_NOTIFICATION_LIB} ${ASKUSER_NOTIFICATION_LIB_DEP_LIBRARIES})
+TARGET_LINK_LIBRARIES(
+ ${TARGET_ASKUSER_NOTIFICATION_LIB}
+ ${TARGET_ASKUSER_COMMON}
+ ${ASKUSER_NOTIFICATION_LIB_DEP_LIBRARIES}
+ )
+
TARGET_LINK_LIBRARIES(${TARGET_ASKUSER_NOTIFICATION_LIB_TEST} ${TARGET_ASKUSER_NOTIFICATION_LIB})
INSTALL(TARGETS ${TARGET_ASKUSER_NOTIFICATION_LIB}
diff --git a/src/ipc-lib/ask-user-channel.cpp b/src/ipc-lib/ask-user-channel.cpp
index 5b7c9f5..e59d0bf 100644
--- a/src/ipc-lib/ask-user-channel.cpp
+++ b/src/ipc-lib/ask-user-channel.cpp
@@ -14,61 +14,35 @@
* limitations under the License
*/
/**
- * @file channel.cpp
+ * @file ask-user-channel.cpp
* @author Bartlomiej Grzelewski
- * @brief
+ * @autor Piotr Sawicki
+ * @autor Rafal Krypa
+ * @brief The implementation of Channel.
*/
-#include
-#include
-#include
-
-#include
-#include
+#include
+#include
+#include
#include
-#include
namespace AskUser {
namespace Protocol {
-void Channel::init() {
- Sock stream(Sock::SRV_STREAM);
- stream.connect(getStreamSocketPath(getuid()));
-
- int fd = stream.getFd();
- m_sockets[fd] = SockDesc(std::move(stream));
-
- m_callbacks->updateConnection(fd, FdMask::READ);
-}
-
-void Channel::parse(const std::string &data, std::vector &parsedData)
-{
- size_t begin = 0;
-
- while (begin < data.size()) {
- size_t end = data.find(' ', begin);
-
- if (end == std::string::npos) {
- parsedData.push_back(data.substr(begin));
- return;
- }
-
- parsedData.push_back(data.substr(begin, end - begin));
- begin = end + 1;
- }
-}
-
-void Channel::process(int fd, int mask) {
+int Channel::process(int fd, int mask) {
try {
auto it = m_sockets.find(fd);
- if (it == m_sockets.end())
- return;
+ if (it == m_sockets.end()) {
+ ALOGE("Cannot find file descriptor " << fd);
+ return -EBADF;
+ }
if (0 == mask) {
- m_callbacks->updateConnection(fd, 0);
+ onClose(fd);
m_sockets.erase(it);
- return;
+ ALOGD("Closing connection on file descriptor: " << fd);
+ return -ENOTCONN;
}
auto &desc = it->second;
@@ -76,42 +50,46 @@ void Channel::process(int fd, int mask) {
if (desc.sock.getType() == Sock::SRV_STREAM) {
Sock client = desc.sock.accept();
int fd = client.getFd();
- if (fd < 0)
- return;
+ if (fd < 0) {
+ ALOGE("Cannot accept a connection on file descriptor: " << desc.sock.getFd());
+ return -EBADF;
+ }
m_sockets[fd] = SockDesc(std::move(client));
- m_callbacks->newConnection(fd, Credentials());
- m_callbacks->updateConnection(fd, FdMask::READ);
- return;
+ onAccept(fd);
+ return 0;
}
if (mask & FdMask::READ) {
int ret = desc.sock.recv(desc.input);
if (ret <= 0) {
- m_callbacks->updateConnection(fd, 0);
+ onClose(fd);
m_sockets.erase(fd);
- return;
+ ALOGE("Cannot read a message from file descriptor: " << fd);
+ return -ENOTCONN;
}
- std::vector params;
- parse(std::string(desc.input.begin(), desc.input.end()), params);
- desc.input.clear();
+ // TODO framing
+ // check that we have the whole message
+ // only then we can extract and parse it
- int command = std::stoi(params[0]);
+ // TODO assume that the message is limited in size
+ // A malicious user can try to allocate memory as much as he or she can.
+ // After detecting such a situation just close a socket.
+ std::vector message;
+ parse(std::string(desc.input.begin(), desc.input.end()), message);
- switch (command) {
- case MSGID_POPUP:
- {
- std::string &privilege = params[1];
- RequestId id = std::strtol(params[2].c_str(), nullptr, 10);
- m_callbacks->popup(fd, id, std::move(privilege));
- break;
- }
- default :
- // TODO log the error
- m_callbacks->updateConnection(fd, 0);
+ // TODO don't clear the buffer, maybe there are some characters
+ // belonging to the next message
+ desc.input.clear();
+
+ int status = onReceive(fd, std::move(message));
+ if (status < 0) {
+ onClose(fd);
m_sockets.erase(fd);
+ ALOGE("Problem while processing received message for file descriptor: " << fd);
+ return -ENOTCONN;
}
}
@@ -119,53 +97,44 @@ void Channel::process(int fd, int mask) {
int size = static_cast(desc.output.size());
int result = desc.sock.send(desc.output);
if (result < 0) {
- m_callbacks->updateConnection(fd, 0);
+ onClose(fd);
m_sockets.erase(fd);
- return;
+ ALOGE("Cannot send a message on file descritptor: " << fd);
+ return -ENOTCONN;
}
if (result == size) {
desc.output.clear();
- m_callbacks->updateConnection(fd, FdMask::READ);
+ onSend(fd);
}
if (result < size) {
desc.output.erase(desc.output.begin(), desc.output.begin()+result);
}
}
- } catch (const std::exception &){
+ } catch (const std::exception &e){
// TODO handle error
+ ALOGE("Unhandled exception occured while processing file descriptor: " << fd);
+ return -ENOTCONN;
}
-}
-void Channel::popupResponse(ConnectionFd fd, RequestId id, int response) {
- try {
- auto it = m_sockets.find(fd);
- if (it == m_sockets.end())
- return;
+ return 0;
+}
- auto &desc = it->second;
+void Channel::parse(const std::string &data, std::vector &parsedData)
+{
+ size_t begin = 0;
- std::stringstream ss;
- ss << id << " " << response;
- std::string o = ss.str();
- std::copy(o.begin(), o.end(), std::back_inserter(desc.output));
- m_callbacks->updateConnection(fd, FdMask::READ | FdMask::WRITE);
- } catch (const std::exception &){}
-}
+ while (begin < data.size()) {
+ size_t end = data.find(' ', begin);
-Channel::~Channel() {
- for (auto &e : m_sockets)
- m_callbacks->updateConnection(e.first, 0);
-}
+ if (end == std::string::npos) {
+ parsedData.push_back(data.substr(begin));
+ return;
+ }
-ChannelPtr createChannel(ServerCallbacksPtr ptr) {
- try {
- Channel *c = new Channel(std::move(ptr));
- c->init();
- return ChannelPtr(c);
- } catch (const std::exception &) {
- return ChannelPtr(nullptr);
+ parsedData.push_back(data.substr(begin, end - begin));
+ begin = end + 1;
}
}
diff --git a/src/ipc-lib/ask-user-client-channel.cpp b/src/ipc-lib/ask-user-client-channel.cpp
index 61ba65e..a59da5c 100644
--- a/src/ipc-lib/ask-user-client-channel.cpp
+++ b/src/ipc-lib/ask-user-client-channel.cpp
@@ -14,107 +14,100 @@
* limitations under the License
*/
/**
- * @file ipc-client.cpp
+ * @file ask-user-client-channel.cpp
* @author Bartlomiej Grzelewski
- * @brief
+ * @author Piotr Sawicki
+ * @brief The implementation of ClientChannel.
*/
+#include
#include
-#include
-#include
-#include
+#include
#include
-#include
-#include
#include
-#define UNUSED __attribute__((unused))
-
namespace AskUser {
namespace Protocol {
-int popup_launch(const std::string &pkgName,
- const std::string &appName,
- uid_t uid,
- const PrivilegeVector &privileges,
- int &result)
-{
- try {
- Sock s(Sock::CLI_STREAM);
- if (0 > s.connect(getStreamSocketPath(uid)))
- return -1;
-
- std::stringstream ss;
- ss << MSGID_POPUP << " " << pkgName << " " << appName << " " << uid;
- for (auto &e : privileges) {
- ss << " " << e;
- }
+ClientChannel::ClientChannel(ClientCallbacksPtr ptr)
+ : m_callbacks(std::move(ptr)) {
+}
- std::string str = ss.str();
+ClientChannel::~ClientChannel() {
+ for (auto &e : m_sockets) {
+ onClose(e.first);
+ }
+}
- if (0 > s.send(RawBuffer(str.begin(), str.end())))
- return -1;
+void ClientChannel::init() {
+ Sock s(Sock::CLI_STREAM);
+ if (0 > s.connect(getStreamSocketPath(geteuid())))
+ throw std::logic_error("Cannot connect to the server");
- RawBuffer resp;
- if (0 > s.wait(FdMask::READ))
- return -1;
- if (0 > s.recv(resp))
- return -1;
+ int fd = s.getFd();
+ m_sockets[fd] = SockDesc(std::move(s));
+}
- std::string input(resp.begin(), resp.end());
- std::stringstream sss(input);
- sss >> result;
+AskUser::Protocol::RequestId ClientChannel::generateRequestId() {
+ static RequestId requestId = 0;
+ return requestId++;
+}
- return 0;
- } catch (const std::exception &) {
- return -1;
+Protocol::RequestId ClientChannel::popupRequest(const std::string &privilege) {
+ if (m_sockets.empty()) {
+ init();
}
-}
-int popup_runtime(UNUSED const std::string &pkgName,
- UNUSED const std::string &appName,
- UNUSED uid_t uid,
- UNUSED std::string &privilege,
- UNUSED int &result)
-{
- return -1;
-}
+ std::stringstream ss;
+ RequestId requestId = generateRequestId();
+ // TODO base64 encode privilege, use g_base64_encode()
+ ss << MSGID_POPUP << " " << privilege << " " << requestId;
+ // client uses only one active socket
+ int fd = m_sockets.begin()->first;
+ std::string str = ss.str();
+ std::copy(str.begin(), str.end(), std::back_inserter(m_sockets[fd].output));
+ m_callbacks->updateConnection(fd, FdMask::READ | FdMask::WRITE);
-int toast_deny(const std::string &pkgName,
- const std::string &appName,
- uid_t uid,
- const std::string &privilege)
-{
- try {
- Sock s(Sock::CLI_DGRAM);
- if (0 > s.connect(getDatagramSocketPath(uid)))
- return -1;
+ return requestId;
+}
- std::string str = std::to_string(MSGID_TOAST1) + " " + pkgName + " " + appName + " " + std::to_string(uid) + " " + privilege;
+void ClientChannel::onAccept(int) {
+}
- return s.send(RawBuffer(str.begin(), str.end()));
- } catch (const std::exception &) {
- return -1;
- }
+void ClientChannel::onClose(int fd) {
+ m_callbacks->updateConnection(fd, 0);
}
-int toast_fail_launch(const std::string &pkgName, const std::string &appName, uid_t uid) {
- try {
- Sock s(Sock::CLI_DGRAM);
- if (0 > s.connect(getDatagramSocketPath(uid)))
- return -1;
+int ClientChannel::onReceive(UNUSED int fd, std::vector &&message) {
+ if (!message.size())
+ return -EINVAL;
- std::string str = std::to_string(MSGID_TOAST2) + " " + pkgName + " " + appName + " " + std::to_string(uid);
+ int command = std::stoi(message[0]);
- return s.send(RawBuffer(str.begin(), str.end()));
- } catch (const std::exception &) {
- return -1;
+ switch (command) {
+ case MSGID_POPUP_RESPONSE:
+ {
+ if (message.size() != 3)
+ return -EINVAL;
+
+ RequestId id = std::strtol(message[1].c_str(), nullptr, 10);
+ int response = std::strtol(message[2].c_str(), nullptr, 10);
+ m_callbacks->popupResponse(id, response);
+ break;
+ }
+ default :
+ return -EINVAL;
}
+
+ return 0;
+}
+
+void ClientChannel::onSend(int fd) {
+ m_callbacks->updateConnection(fd, FdMask::READ);
}
} // namespace Protocol
} // namespace AskUser
-
diff --git a/src/ipc-lib/ask-user-config.cpp b/src/ipc-lib/ask-user-config.cpp
index 19f9364..597abe6 100644
--- a/src/ipc-lib/ask-user-config.cpp
+++ b/src/ipc-lib/ask-user-config.cpp
@@ -16,7 +16,7 @@
/**
* @file ask-user-config.cpp
* @author Bartlomiej Grzelewski
- * @brief
+ * @brief The implementation of utility functions for getting sockets paths.
*/
#include
diff --git a/src/ipc-lib/ask-user-config.h b/src/ipc-lib/ask-user-config.h
index 7b77be4..e6ed815 100644
--- a/src/ipc-lib/ask-user-config.h
+++ b/src/ipc-lib/ask-user-config.h
@@ -16,18 +16,13 @@
/**
* @file ask-user-config.h
* @author Bartlomiej Grzelewski
- * @brief
+ * @brief The declaration of utility functions for getting sockets paths.
*/
#pragma once
#include
#include
-// We want to use it constat expressions (this is the reason why it's not in cpp file
-const int MSGID_POPUP = 1;
-const int MSGID_TOAST1 = 2;
-const int MSGID_TOAST2 = 3;
-
std::string getDatagramSocketPath(uid_t uid);
std::string getStreamSocketPath(uid_t uid);
diff --git a/src/ipc-lib/ask-user-server-channel.cpp b/src/ipc-lib/ask-user-server-channel.cpp
new file mode 100644
index 0000000..ba72edb
--- /dev/null
+++ b/src/ipc-lib/ask-user-server-channel.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co.
+ *
+ * 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
+ */
+/**
+ * @file ask-user-server-channel.cpp
+ * @author Bartlomiej Grzelewski
+ * @author Piotr Sawicki
+ * @brief The implementation of ServerChannel.
+ */
+#include
+#include
+
+#include
+
+#include
+
+namespace AskUser {
+namespace Protocol {
+
+ServerChannel::ServerChannel(ServerCallbacksPtr ptr)
+ : m_callbacks(std::move(ptr))
+{
+ init();
+}
+
+ServerChannel::~ServerChannel() {
+ for (auto &e : m_sockets) {
+ onClose(e.first);
+ }
+}
+
+void ServerChannel::init() {
+ Sock stream(Sock::SRV_STREAM);
+ stream.connect(getStreamSocketPath(geteuid()));
+
+ int fd = stream.getFd();
+ m_sockets[fd] = SockDesc(std::move(stream));
+
+ m_callbacks->updateConnection(fd, FdMask::READ);
+}
+
+void ServerChannel::popupResponse(ConnectionFd fd, RequestId id, int response) {
+ try {
+ auto it = m_sockets.find(fd);
+ if (it == m_sockets.end())
+ return;
+
+ auto &desc = it->second;
+
+ std::stringstream ss;
+ ss << MSGID_POPUP_RESPONSE << " " << id << " " << response;
+ std::string o = ss.str();
+ std::copy(o.begin(), o.end(), std::back_inserter(desc.output));
+
+ m_callbacks->updateConnection(fd, FdMask::READ | FdMask::WRITE);
+ } catch (const std::exception &){}
+}
+
+void ServerChannel::onAccept(int fd) {
+ m_callbacks->newConnection(fd, Credentials());
+ m_callbacks->updateConnection(fd, FdMask::READ);
+}
+
+void ServerChannel::onClose(int fd) {
+ m_callbacks->updateConnection(fd, 0);
+}
+
+int ServerChannel::onReceive(int fd, std::vector &&message) {
+ if (!message.size())
+ return -1;
+
+ int command = std::stoi(message[0]);
+
+ switch (command) {
+ case MSGID_POPUP:
+ {
+ if (message.size() != 3)
+ return -1;
+
+ std::string &privilege = message[1];
+ RequestId requestId = std::strtol(message[2].c_str(), nullptr, 10);
+ // TODO base64 decode privilege. Privilege may contain
+ // any character: \n, space, etc. use g_base64_decode()
+ m_callbacks->popup(fd, requestId, std::move(privilege));
+ break;
+ }
+ default :
+ return -1;
+ }
+
+ return 0;
+}
+
+void ServerChannel::onSend(int fd) {
+ m_callbacks->updateConnection(fd, FdMask::READ);
+}
+
+} // namespace Protocol
+} // namespace AskUser
diff --git a/src/ipc-lib/askuser-notification/ask-user-channel.h b/src/ipc-lib/askuser-notification/ask-user-channel.h
new file mode 100644
index 0000000..7bd3658
--- /dev/null
+++ b/src/ipc-lib/askuser-notification/ask-user-channel.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co.
+ *
+ * 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
+ */
+/**
+ * @file ask-user-channel.h
+ * @author Bartlomiej Grzelewski
+ * @author Piotr Sawicki
+ * @brief The declaration of Channel.
+ */
+#pragma once
+
+
+#include