--- /dev/null
+SET(TARGET_PROTOCOL "protocol")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -ggdb -O0")
+
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}
+ )
+
+SET(PROTOCOL_SOURCES
+ ${PROJECT_SOURCE_DIR}/channel.cpp
+ ${PROJECT_SOURCE_DIR}/ask-user-client.cpp
+ ${PROJECT_SOURCE_DIR}/sock.cpp
+ ${PROJECT_SOURCE_DIR}/ask-user-config.cpp
+ )
+
+ADD_LIBRARY(${TARGET_PROTOCOL} SHARED ${PROTOCOL_SOURCES})
+
+TARGET_LINK_LIBRARIES(${TARGET_PROTOCOL})
+
+
+SET(TARGET_PTEST "test")
+
+SET(TARGET_PTEST_SOURCES
+ ${PROJECT_SOURCE_DIR}/main.cpp
+ )
+
+ADD_EXECUTABLE(${TARGET_PTEST} ${TARGET_PTEST_SOURCES})
+
+TARGET_LINK_LIBRARIES(${TARGET_PTEST} ${TARGET_PROTOCOL})
+
+
+
+
--- /dev/null
+/*
+ * 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 ipc-client.cpp
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#include <sstream>
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <ask-user/ask-user-client.h>
+#include <ask-user/ask-user-service.h>
+
+#include <ask-user-config.h>
+#include <sock.h>
+
+namespace AskUser {
+namespace Protocol {
+
+int popup_launch(const std::string &pkgName,
+ const std::string &appName,
+ uid_t uid,
+ const PrivilegeVector &privileges,
+ int &result)
+{
+ try {
+ std::string path = SOCKET_STREAM_PATH + "." + std::to_string(uid);
+ Sock s(Sock::CLI_STREAM);
+ if (0 > s.connect(path))
+ return -1;
+
+ std::stringstream ss;
+ ss << MSGID_POPUP << " " << pkgName << " " << appName << " " << uid;
+ for (auto &e : privileges) {
+ ss << " " << e;
+ }
+
+ std::string str = ss.str();
+
+ if (0 > s.send(RawBuffer(str.begin(), str.end())))
+ return -1;
+
+ RawBuffer resp;
+ if (0 > s.wait(FdMask::READ))
+ return -1;
+ if (0 > s.recv(resp))
+ return -1;
+
+ std::string input(resp.begin(), resp.end());
+ std::stringstream sss(input);
+ sss >> result;
+
+ return 0;
+ } catch (const std::exception &) {
+ return -1;
+ }
+}
+
+int popup_runtime(const std::string &pkgName,
+ const std::string &appName,
+ uid_t uid,
+ std::string &privilege,
+ int &result)
+{
+ return -1;
+}
+
+
+int toast_deny(const std::string &pkgName,
+ const std::string &appName,
+ uid_t uid,
+ const std::string &privilege)
+{
+ try {
+ std::string path = SOCKET_DGRAM_PATH + "." + std::to_string(uid);
+ Sock s(Sock::CLI_DGRAM);
+ if (0 > s.connect(path))
+ return -1;
+
+ std::string str = std::to_string(MSGID_TOAST1) + " " + pkgName + " " + appName + " " + std::to_string(uid) + " " + privilege;
+
+ return s.send(RawBuffer(str.begin(), str.end()));
+ } catch (const std::exception &) {
+ return -1;
+ }
+}
+
+int toast_fail_launch(const std::string &pkgName, const std::string &appName, uid_t uid) {
+ try {
+ std::string path = SOCKET_DGRAM_PATH + "." + std::to_string(uid);
+ Sock s(Sock::CLI_DGRAM);
+ if (0 > s.connect(path))
+ return -1;
+
+ std::string str = std::to_string(MSGID_TOAST2) + " " + pkgName + " " + appName + " " + std::to_string(uid);
+
+ return s.send(RawBuffer(str.begin(), str.end()));
+ } catch (const std::exception &) {
+ return -1;
+ }
+}
+
+} // namespace Protocol
+} // namespace AskUser
+
+
--- /dev/null
+/*
+ * 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-config.cpp
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#include <ask-user-config.h>
+
+const std::string SOCKET_STREAM_PATH("/tmp/ask-user-stream");
+const std::string SOCKET_DGRAM_PATH("/tmp/ask-user-dgram");
+
+//const int MSGID_POPUP = 1;
+//const int MSGID_TOUST1 = 2;
+//const int MSGID_TOUST2 = 3;
+//
--- /dev/null
+/*
+ * 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-config.h
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#pragma once
+
+#include <string>
+
+extern const std::string SOCKET_STREAM_PATH;
+extern const std::string SOCKET_DGRAM_PATH;
+
+// 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;
+
--- /dev/null
+/*
+ * 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-client.h
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#pragma once
+
+#include <sys/types.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <ask-user/ask-user-types.h>
+
+namespace AskUser {
+namespace Protocol {
+/**
+ * Synchronous request for showing popup.
+ *
+ * \param[in] pkgName Application package name.
+ * \param[in] appName Application name.
+ * \param[in] uid Information about user that should see popup.
+ * \param[in] privileges List of privileges that should be shown to user.
+ * \param[out] result Result returned by ask-user application.
+ *
+ * \return Value less that 0 means ipc error.
+ */
+ int popup_launch(const std::string &pkgName, const std::string &appName, uid_t uid, const PrivilegeVector &privileges, int &result);
+
+ /**
+ * Synchronous request for showing popup.
+ *
+ * \param[in] pkgName Application package name.
+ * \param[in] appName Application name.
+ * \param[in] uid Information about user that should see popup.
+ * \param[in] privilege Privilege that should be shown to user.
+ * \param[out] result Result returned by ask-user application.
+ *
+ * \return Value less that 0 means ipc error.
+ */
+ int popup_runtime(const std::string &pkgName, const std::string &appName, uid_t uid, std::string &privilege, int &result);
+
+/**
+ * Nonblocking request for showing toast.
+ *
+ * \param[in] pkgName Application package name.
+ * \param[in] appName Application name.
+ * \param[in] uid Information about user that should see popup.
+ * \param[in] privilege Name of privilege that was denied.
+ *
+ * \return Value less that 0 means ipc error.
+ */
+int toast_deny(const std::string &pkgName, const std::string &appName, uid_t uid, const std::string &privilege);
+
+/**
+ * Nonblocking request for showing toast.
+ *
+ * \param[in] pkgName Application package name.
+ * \param[in] appName Application name.
+ * \param[in] uid Information about user that should see popup.
+ *
+ * \return Value less that 0 means ipc error.
+ */
+int toast_fail_launch(const std::string &pkgName, const std::string &appName, uid_t uid);
+
+} // namespace Protocol
+} // namespace AskUser
+
--- /dev/null
+/*
+ * 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-service.h
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#pragma once
+
+#include <sys/types.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <ask-user/ask-user-types.h>
+
+namespace AskUser {
+namespace Protocol {
+
+enum FdMask {
+ READ = 1,
+ WRITE = 2,
+};
+
+/**
+ * IServiceCallbacks defines set of callbacks that must be implemented in service.
+ */
+
+struct IServerCallbacks {
+
+ virtual ~IServerCallbacks(){}
+ /**
+ * This function gives you number of descriptor that should be watched by poll/select.
+ *
+ * \param[in] fd Number of opened descriptor.
+ * \param[in] mask Type of acction that is required on this descriptor.
+ * mask == 0 remove descriptor fd from watched pool
+ * mask == 1 watch descriptor for READ
+ * mask == 2 watch descriptor for WRITE
+ * maks == 3 watch descriptor for READ and WRITE
+ */
+ virtual void updateFd(int fd, int mask) = 0;
+ /**
+ * some client called popup function with parameters.
+ */
+ virtual void popup_launch(int requestId, const std::string &pkgName, const std::string &appName, uid_t uid, const PrivilegeVector &privileges) = 0;
+ /**
+ * some client called test_deny function with parameters.
+ */
+ virtual void toast_deny(const std::string &pkgName, const std::string &appName, uid_t uid, const Privilege &privilege) = 0;
+ /**
+ * some client called toast_fail_launch function with parameters.
+ */
+ virtual void toast_fail_launch(const std::string &pkgName, const std::string &appName, uid_t uid) = 0;
+};
+
+struct IChannel {
+ virtual ~IChannel(){}
+
+ /**
+ * Process function should be called each time some event is reported by poll/select on
+ * descriptor.
+ *
+ * \param[in] fd Number of descriptor.
+ * \param[in] mask Information about event that is waiting on descriptor
+ * (FdMask::READ or FdMask::WRITE). If you pass 0 for some reason
+ * the descriptor will be closed and callback updateFd will be called
+ * with mask = 0
+ */
+ virtual void process(int fd, int mask) = 0;
+
+ /**
+ * Information about action that was choosed by user.
+ *
+ * \param[in] requestId Request number.
+ * \param[in] response Information about action choosed by user.
+ */
+ virtual void popupResponse(int requestId, int response) = 0;
+};
+
+typedef std::unique_ptr<IChannel> ChannelPtr;
+typedef std::unique_ptr<IServerCallbacks> ServerCallbacksPtr;
+
+ChannelPtr createChannel(ServerCallbacksPtr ptr);
+
+} // namespace Protocol
+} // namespace AskUser
+
--- /dev/null
+/*
+ * 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-types.h
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#pragma once
+
+#define ASKUSER_DENY_ONCE 0
+#define ASKUSER_DENY_FOREVER 1
+#define ASKUSER_ALLOW_ONCE 2
+#define ASKUSER_ALLOW_FOREVER 3
+#define ASKUSER_UNKNOWN_ERROR -255
+
+namespace AskUser {
+namespace Protocol {
+
+typedef std::string Privilege;
+typedef std::vector<Privilege> PrivilegeVector;
+
+} // namespace Protocol
+} // AskUser
+
--- /dev/null
+/*
+ * 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 channel.cpp
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#include <sstream>
+#include <string>
+
+#include <ask-user/ask-user-service.h>
+
+#include <ask-user-config.h>
+#include <channel.h>
+#include <sock.h>
+
+namespace AskUser {
+namespace Protocol {
+
+void Channel::init() {
+ Sock stream(Sock::SRV_STREAM);
+ Sock datagram(Sock::SRV_DGRAM);
+
+ uid_t uid = getuid();
+ std::string path = SOCKET_STREAM_PATH + "." + std::to_string(uid);
+ stream.connect(path);
+ path = SOCKET_DGRAM_PATH + "." + std::to_string(uid);
+ datagram.connect(path);
+
+ int fd1 = stream.getFd();
+ int fd2 = datagram.getFd();
+
+ m_socket[fd1] = SockDesc(std::move(stream));
+ m_socket[fd2] = SockDesc(std::move(datagram));
+
+ m_callbacks->updateFd(fd1, FdMask::READ);
+ m_callbacks->updateFd(fd2, FdMask::READ);
+}
+
+void Channel::process(int fd, int mask) {
+ try {
+ auto it = m_socket.find(fd);
+ if (it == m_socket.end())
+ return;
+
+ if (0 == mask) {
+ m_socket.erase(it);
+ m_callbacks->updateFd(fd, 0);
+ return;
+ }
+
+ auto &desc = it->second;
+
+ if (desc.sock.getType() == Sock::SRV_STREAM) {
+ Sock client = desc.sock.accept();
+ int fd = client.getFd();
+ if (fd < 0)
+ return;
+ m_socket[fd] = SockDesc(std::move(client));
+ m_callbacks->updateFd(fd, FdMask::READ);
+ return;
+ }
+
+ if (mask & FdMask::READ) {
+ int ret = desc.sock.recv(desc.input);
+
+ if (ret <= 0) {
+ m_socket.erase(fd);
+ m_callbacks->updateFd(fd, 0);
+ return;
+ }
+
+ std::string data(desc.input.begin(), desc.input.end());
+ desc.input.clear();
+ std::stringstream ss(data);
+
+ int command;
+ std::string appId, pkgName;
+ uid_t uid;
+
+ ss >> command >> pkgName >> appId >> uid;
+
+ switch(command) {
+ case MSGID_POPUP:
+ {
+ PrivilegeVector vect;
+ std::string privilege;
+ while(ss) {
+ ss >> privilege;
+ vect.push_back(privilege);
+ }
+ m_callbacks->popup_launch(fd, pkgName, appId, uid, vect);
+ break;
+ }
+ case MSGID_TOAST1:
+ {
+ std::string privilege;
+ ss >> privilege;
+ m_callbacks->toast_deny(pkgName, appId, uid, privilege);
+ break;
+ }
+ case MSGID_TOAST2:
+ {
+ m_callbacks->toast_fail_launch(pkgName, appId, uid);
+ break;
+ }
+ }
+ }
+
+ if (mask & FdMask::WRITE) {
+ int size = static_cast<int>(desc.output.size());
+ int result = desc.sock.send(desc.output);
+ if (result < 0) {
+ m_socket.erase(fd);
+ m_callbacks->updateFd(fd, 0);
+ return;
+ }
+
+ if (result == size) {
+ desc.output.clear();
+ m_callbacks->updateFd(fd, FdMask::READ);
+ }
+
+ if (result < size) {
+ desc.output.erase(desc.output.begin(), desc.output.begin()+result);
+ }
+ }
+ } catch (const std::exception &){}
+}
+
+void Channel::popupResponse(int requestId, int response) {
+ try {
+ auto it = m_socket.find(requestId);
+ if (it == m_socket.end())
+ return;
+
+ auto &desc = it->second;
+
+ std::stringstream ss;
+ ss << response;
+ std::string o = ss.str();
+
+ std::copy(o.begin(), o.end(), std::back_inserter(desc.output));
+ m_callbacks->updateFd(requestId, FdMask::READ | FdMask::WRITE);
+ } catch (const std::exception &){}
+}
+
+Channel::~Channel() {
+ for (auto &e : m_socket)
+ m_callbacks->updateFd(e.first, 0);
+}
+
+ChannelPtr createChannel(ServerCallbacksPtr ptr) {
+ try {
+ Channel *c = new Channel(std::move(ptr));
+ c->init();
+ return ChannelPtr(c);
+ } catch (const std::exception &) {
+ return ChannelPtr(nullptr);
+ }
+}
+
+} // namespace Protocol
+} // namespace AskUser
+
--- /dev/null
+/*
+ * 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 channel.h
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#pragma once
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <ask-user/ask-user-service.h>
+#include <raw-buffer.h>
+#include <sock.h>
+
+
+namespace AskUser {
+namespace Protocol {
+
+struct SockDesc {
+ SockDesc(Sock psock)
+ : sock(std::move(psock))
+ {}
+ SockDesc(){}
+ Sock sock;
+ RawBuffer input;
+ RawBuffer output;
+};
+
+typedef std::map<int, SockDesc> SocketMap;
+
+class Channel : public IChannel {
+public:
+ Channel(ServerCallbacksPtr ptr)
+ : m_callbacks(std::move(ptr))
+ {}
+
+ void init();
+ virtual void process(int fd, int mask);
+ virtual void popupResponse(int requestId, int response);
+ virtual ~Channel();
+
+private:
+ ServerCallbacksPtr m_callbacks;
+ SocketMap m_socket;
+};
+
+} // namespace Protocol
+} // namespace AskUser
+
--- /dev/null
+/*
+ * 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 main.cpp
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#include <map>
+
+#include <poll.h>
+#include <unistd.h>
+
+#include <ask-user/ask-user-client.h>
+#include <ask-user/ask-user-service.h>
+
+std::map<int, int> m_sockets;
+
+using namespace AskUser::Protocol;
+
+struct Callbacks : public IServerCallbacks {
+ Callbacks() : m_channel(nullptr) {}
+
+ virtual void updateFd(int fd, int mask) {
+ printf("call updateFd %d %d\n", fd, mask);
+ if (mask == 0) {
+ m_sockets.erase(fd);
+ return;
+ }
+ m_sockets[fd] = mask;
+ }
+
+ virtual void popup_launch(int requestId, const std::string &pkgName, const std::string &appName, uid_t uid, const PrivilegeVector &priv) {
+ printf("call popup %s %s %d\n", pkgName.c_str(), appName.c_str(), uid);
+ if (m_channel)
+ m_channel->popupResponse(requestId, 0xdeadbeef);
+ }
+
+ virtual void toast_deny(const std::string &pkgName, const std::string &appName, uid_t uid, const Privilege &privilege) {
+ printf("call toast_deny %s %s %d\n", pkgName.c_str(), appName.c_str(), uid);
+ }
+
+ virtual void toast_fail_launch(const std::string &pkgName, const std::string &appName, uid_t uid) {
+ printf("call toast_fail_launch %s %s %d\n", pkgName.c_str(), appName.c_str(), uid);
+ }
+
+ void setChannel(IChannel *ptr) {
+ m_channel = ptr;
+ }
+
+private:
+ IChannel *m_channel;
+};
+
+void server(void) {
+ Callbacks *c = new Callbacks;
+ ChannelPtr ptr = createChannel(ServerCallbacksPtr(c));
+ c->setChannel(ptr.get());
+
+ pollfd fd[100];
+
+ while(1) {
+ int last = 0;
+ for (auto &e : m_sockets) {
+ fd[last].fd = e.first;
+ fd[last].revents = 0;
+ fd[last].events = ((e.second & FdMask::READ) ? POLLIN : 0) | ((e.second & FdMask::WRITE) ? POLLOUT : 0);
+ last++;
+ }
+ if (-1 == poll(fd, last, -1)) {
+ printf("Error in poll. Quit\n");
+ return;
+ }
+ for (int i=0; i<last; ++i) {
+ if (fd[i].revents & POLLIN)
+ ptr->process(fd[i].fd, FdMask::READ);
+ if (fd[i].revents & POLLOUT)
+ ptr->process(fd[i].fd, FdMask::WRITE);
+ }
+ }
+}
+
+void stream() {
+ PrivilegeVector vect = {"one", "two"};
+ int result;
+ int ret = popup_launch("spkg", "sapp", getuid(), vect, result);
+ printf("Sended stream. Result: %x\n", result);
+}
+
+void toust1() {
+ toast_deny("tpkg1", "sapp1", getuid(), "some_priv");
+ printf("sended\n");
+}
+
+void toust2() {
+ toast_fail_launch("tpkg2", "sapp2", getuid());
+ printf("sended\n");
+}
+
+int main(){
+ int com;
+ printf("0 - server, 1 - send stream, 2 - send toust1, 3 - send toust2\n>");
+ scanf("%d", &com);
+
+ switch(com) {
+ case 0:
+ server();
+ break;
+ case 1:
+ stream();
+ break;
+ case 2:
+ toust1();
+ break;
+ case 3:
+ toust2();
+ break;
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * 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 raw-buffer.h
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief
+ */
+#pragma once
+
+#include <vector>
+
+namespace AskUser {
+namespace Protocol {
+
+typedef std::vector<unsigned char> RawBuffer;
+
+} // namespace Protocol
+} // namespace AskUser
+
--- /dev/null
+/*
+ * 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 Sock.cpp
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief Implementation of Sock methods
+ */
+#include <poll.h>
+#include <stdexcept>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#ifdef WITH_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif // WITH_SYSTEMD
+
+#include <string>
+#include <vector>
+
+#include <ask-user/ask-user-service.h>
+
+#include <sock.h>
+
+namespace {
+
+int getSocketFromSystemD() {
+#ifdef WITH_SYSTEMD
+ int n = sd_listen_fds(0);
+
+ if (n < 0)
+ return -1;
+
+ for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START+n; ++fd)
+ if (0 < sd_is_socket_unix(fd, getUnixSockType, 1, m_path.c_str(), 0))
+ return fd;
+#endif // WITH_SYSTEMD
+ return -1;
+}
+
+} // namespace Anonymous
+
+namespace AskUser {
+namespace Protocol {
+
+Sock::Sock(Sock &&second)
+ : m_type(second.m_type)
+ , m_fd(second.m_fd)
+{
+ second.m_fd = -1;
+}
+
+Sock::Sock(Sock::Type type, int fd)
+ : m_type(type)
+ , m_fd(fd)
+{}
+
+Sock& Sock::operator=(Sock &&second) {
+ if (this == &second)
+ return *this;
+
+ close();
+
+ m_fd = second.m_fd;
+ m_type = second.m_type;
+
+ second.m_fd = -1;
+
+ return *this;
+}
+
+
+int Sock::getUnixSockType() const {
+ switch(m_type) {
+ case SRV_DGRAM:
+ case CLI_DGRAM:
+ return SOCK_DGRAM;
+ case SRV_STREAM:
+ case CLI_STREAM:
+ return SOCK_STREAM;
+ }
+ return 0;
+}
+
+int Sock::connect(const std::string &path) {
+ if (m_fd != -1)
+ return -1;
+
+ m_path = path;
+
+ bool policySystemD = true;
+ bool policyUnlink = true;
+ bool policySocket = true;
+ bool policyBind = true;
+ bool policyListen = true;
+ bool policyConnect = true;
+
+ switch(m_type) {
+ case SRV_STREAM:
+ policyConnect = false;
+ break;
+ case CLI_STREAM:
+ policySystemD = false;
+ policyUnlink = false;
+ policyBind = false;
+ policyListen = false;
+ break;
+ case SRV_DGRAM:
+ policyListen = false;
+ policyConnect = false;
+ break;
+ case CLI_DGRAM:
+ policySystemD = false;
+ policyUnlink = false;
+ policyBind = false;
+ policyListen = false;
+ policyConnect = false;
+ break;
+ }
+
+ if (m_fd != -1) {
+ return -1;
+ }
+
+ if (policySystemD) {
+ m_fd = getSocketFromSystemD();
+ if (m_fd >= 0) {
+ policyUnlink = false;
+ policySocket = false;
+ policyBind = false;
+ }
+ }
+
+ if (policyUnlink)
+ ::unlink(m_path.c_str()); // we ignore return value by design
+
+ if (policySocket)
+ m_fd = ::socket(AF_UNIX, getUnixSockType(), 0);
+
+ if (m_fd < 0)
+ return -1;
+
+ // remote is used in bind and in connect
+ sockaddr_un remote;
+ auto length = sizeof(sockaddr_un);
+ if (policyBind || policyConnect) {
+ remote.sun_family = AF_UNIX;
+ if (path.size() >= sizeof(remote.sun_path)) {
+ close();
+ return -1;
+ }
+ memcpy(remote.sun_path, path.c_str(), path.size()+1);
+ }
+
+ if (policyBind && (-1 == ::bind(m_fd, reinterpret_cast<sockaddr *>(&remote), sizeof(remote)))) {
+ close();
+ return -1;
+ }
+
+ if (policyListen && (-1 == ::listen(m_fd, 5))) {
+ close();
+ return -1;
+ }
+
+ if (policyConnect && (-1 == TEMP_FAILURE_RETRY(::connect(m_fd, reinterpret_cast<sockaddr *>(&remote), static_cast<socklen_t>(length)))))
+ {
+ close();
+ return -1;
+ }
+ return 0;
+}
+
+Sock Sock::accept() {
+ int retFd = TEMP_FAILURE_RETRY(::accept(m_fd, nullptr, nullptr));
+ if (retFd < 0) {
+ return Sock(CLI_STREAM, -1);
+ }
+ return Sock(CLI_STREAM, retFd);
+}
+
+int Sock::send(const RawBuffer &buffer) {
+ static const int flags = MSG_NOSIGNAL | MSG_DONTWAIT;
+ if (m_fd < 0)
+ return -1;
+
+ switch(m_type) {
+ default:
+ return -1;
+ case CLI_STREAM:
+ {
+ return static_cast<int>(
+ TEMP_FAILURE_RETRY(::send(m_fd, buffer.data(), buffer.size(), flags)));
+ }
+ case CLI_DGRAM:
+ {
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ memcpy(addr.sun_path, m_path.data(), m_path.size());
+ return static_cast<int>(
+ TEMP_FAILURE_RETRY(::sendto(m_fd, buffer.data(), buffer.size(), flags,
+ reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr))));
+ }
+ }
+}
+
+int Sock::wait(int mask) {
+ pollfd fd = {};
+
+ fd.fd = m_fd;
+ fd.events = (mask & FdMask::READ ? POLLIN : 0) | (mask & FdMask::WRITE ? POLLOUT : 0);
+
+ if (fd.events == 0)
+ return -1;
+
+ if (0 > ::poll(&fd, 1, -1))
+ return -1;
+ return 0;
+}
+
+int Sock::recv(RawBuffer &output) {
+ if (m_fd < 0)
+ return -1;
+
+ switch(m_type) {
+ default:
+ return -1;
+ case CLI_STREAM:
+ case SRV_DGRAM:
+ {
+ RawBuffer buffer(4096);
+ int result = TEMP_FAILURE_RETRY(::recv(m_fd, buffer.data(), buffer.size(), MSG_DONTWAIT));
+ if (result > 0)
+ std::copy(buffer.begin(), buffer.begin()+result, std::back_inserter(output));
+ return static_cast<int>(result);
+ }
+ }
+}
+
+void Sock::close() {
+ if (m_fd >= 0)
+ ::close(m_fd);
+ m_fd = -1;
+}
+
+} // namespace Protocol
+} // namespace AskUser
+
--- /dev/null
+/*
+ * 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 Sock.cpp
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @brief Declaration of client/server Sock wrapper
+ */
+
+#pragma once
+
+#include <string>
+#include <unistd.h>
+
+#include <raw-buffer.h>
+
+namespace AskUser {
+namespace Protocol {
+
+class Sock {
+public:
+ enum Type {
+ SRV_STREAM, // server side STREAM socket (you may call accept on it)
+ // accept will always return CLI_STREAM
+ CLI_STREAM, // client side STREAM socket
+ SRV_DGRAM, // server side DATAGRAM socket
+ CLI_DGRAM, // client side DATAGRAM socket
+ };
+
+ Sock(Type type = SRV_STREAM, int fd = -1);
+
+ Sock(const Sock &other) = delete;
+ Sock &operator=(const Sock &other) = delete;
+
+ Sock(Sock &&other);
+ Sock &operator=(Sock &&other);
+
+ virtual ~Sock() { close(); }
+
+ int getFd() const { return m_fd; }
+ int getType() const { return m_type; }
+ int getUnixSockType() const;
+
+
+ int connect(const std::string &path);
+ Sock accept();
+ void close();
+
+ int wait(int mask);
+ int recv(RawBuffer &buffer);
+ int send(const RawBuffer &buffer);
+
+private:
+ Type m_type;
+ int m_fd;
+ std::string m_path;
+};
+
+} // namespace Protocol
+} // namespace AskUser
+