mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
mkdir -p %{buildroot}%{_unitdir}/sockets.target.wants
ln -s ../%{service_name}.service %{buildroot}%{_unitdir}/multi-user.target.wants/%{service_name}.service
-ln -s ../%{service_name}.socket %{buildroot}%{_unitdir}/sockets.target.wants/%{service_name}.socket
+ln -s ../%{service_name}-cs.socket %{buildroot}%{_unitdir}/sockets.target.wants/%{service_name}-cs.socket
+ln -s ../%{service_name}-wp.socket %{buildroot}%{_unitdir}/sockets.target.wants/%{service_name}-wp.socket
+ln -s ../%{service_name}-admin.socket %{buildroot}%{_unitdir}/sockets.target.wants/%{service_name}-admin.socket
ln -s ../%{service_name}-popup.socket %{buildroot}%{_unitdir}/sockets.target.wants/%{service_name}-popup.socket
mkdir -p %{buildroot}%{ro_data_dir}/license
%post
systemctl daemon-reload
if [ $1 = 1 ]; then
- systemctl start %{service_name}.socket
- systemctl start %{service_name}.service
+ systemctl start %{service_name}-cs.socket
+ systemctl start %{service_name}-wp.socket
+ systemctl start %{service_name}-admin.socket
systemctl start %{service_name}-popup.socket
+ systemctl start %{service_name}.service
fi
if [ $1 = 2 ]; then
- systemctl restart %{service_name}.socket
- systemctl restart %{service_name}.service
+ systemctl restart %{service_name}-cs.socket
+ systemctl restart %{service_name}-wp.socket
+ systemctl restart %{service_name}-admin.socket
systemctl restart %{service_name}-popup.socket
+ systemctl restart %{service_name}.service
fi
%preun
if [ $1 = 0 ]; then
systemctl stop %{service_name}.service
- systemctl stop %{service_name}.socket
+ systemctl stop %{service_name}-cs.socket
+ systemctl stop %{service_name}-wp.socket
+ systemctl stop %{service_name}-admin.socket
systemctl stop %{service_name}-popup.socket
fi
%{bin_dir}/%{service_name}-popup
%{_unitdir}/multi-user.target.wants/%{service_name}.service
%{_unitdir}/%{service_name}.service
-%{_unitdir}/sockets.target.wants/%{service_name}.socket
-%{_unitdir}/%{service_name}.socket
%{_unitdir}/%{service_name}-popup.service
+%{_unitdir}/sockets.target.wants/%{service_name}-cs.socket
+%{_unitdir}/sockets.target.wants/%{service_name}-wp.socket
+%{_unitdir}/sockets.target.wants/%{service_name}-admin.socket
%{_unitdir}/sockets.target.wants/%{service_name}-popup.socket
+%{_unitdir}/%{service_name}-cs.socket
+%{_unitdir}/%{service_name}-wp.socket
+%{_unitdir}/%{service_name}-admin.socket
%{_unitdir}/%{service_name}-popup.socket
%dir %{ro_data_dir}/%{service_name}
<smack request="pkgmgr::db" type="rwx" />
</request>
<permit>
- <smack permit="_" type="rx" />
+ <smack permit="_" type="rwx" />
<smack permit="xorg" type="rx" />
<smack permit="pkgmgr" type="rx" />
<smack permit="pkgmgr-server" type="rx" />
common/mainloop.cpp
common/service.cpp
common/socket.cpp
+ common/socket-descriptor.cpp
common/credential.cpp
)
m_cb(handle->m_cb),
m_userdata(userdata),
m_isStopped(isStopped),
- m_dispatcher(new Dispatcher("/tmp/." SERVICE_NAME ".socket"))
+ m_dispatcher(new Dispatcher(SockId::CS))
{
// disable ask user option for async request for now
copyKvp<int>(CsContext::Key::CoreUsage);
return CSR_ERROR_INVALID_PARAMETER;
*phandle = reinterpret_cast<csr_cs_context_h>(
- new Client::HandleExt(ContextShPtr(new CsContext())));
+ new Client::HandleExt(SockId::CS, ContextShPtr(new CsContext())));
return CSR_ERROR_NONE;
namespace Csr {
namespace Client {
-HandleExt::HandleExt(ContextShPtr &&context) :
- Handle(std::move(context)),
+HandleExt::HandleExt(SockId id, ContextShPtr &&context) :
+ Handle(id, std::move(context)),
m_stop(false)
{
}
class HandleExt : public Handle {
public:
- explicit HandleExt(ContextShPtr &&);
+ explicit HandleExt(SockId id, ContextShPtr &&);
virtual ~HandleExt();
void dispatchAsync(const Task &task);
namespace Csr {
namespace Client {
-Handle::Handle(ContextShPtr &&context) :
- m_ctx(std::forward<ContextShPtr>(context))
+Handle::Handle(SockId id, ContextShPtr &&context) :
+ m_sockId(id), m_ctx(std::forward<ContextShPtr>(context))
{
if (!m_ctx)
ThrowExc(InvalidParam, "context shouldn't be null");
}
+Handle::Handle(SockId id) : m_sockId(id)
+{
+}
+
Handle::~Handle()
{
}
#include "common/icontext.h"
#include "common/dispatcher.h"
+#include "common/socket-descriptor.h"
namespace Csr {
namespace Client {
class Handle {
public:
- explicit Handle(ContextShPtr &&);
+ explicit Handle(SockId, ContextShPtr &&);
+ explicit Handle(SockId);
virtual ~Handle();
template<typename Type, typename ...Args>
std::vector<ResultListPtr> m_resultLists;
private:
+ SockId m_sockId;
std::unique_ptr<Dispatcher> m_dispatcher;
ContextShPtr m_ctx;
};
Type Handle::dispatch(Args &&...args)
{
if (m_dispatcher == nullptr)
- m_dispatcher.reset(new Dispatcher("/tmp/." SERVICE_NAME ".socket"));
+ m_dispatcher.reset(new Dispatcher(m_sockId));
return m_dispatcher->methodCall<Type>(std::forward<Args>(args)...);
}
return CSR_ERROR_INVALID_PARAMETER;
*phandle = reinterpret_cast<csr_wp_context_h>(
- new Client::Handle(std::make_shared<WpContext>()));
+ new Client::Handle(SockId::WP, std::make_shared<WpContext>()));
return CSR_ERROR_NONE;
return m_socket.read();
}
-int Connection::getFd() const
+SockId Connection::getSockId() const noexcept
+{
+ return m_socket.getSockId();
+}
+
+int Connection::getFd() const noexcept
{
return m_socket.getFd();
}
void send(const RawBuffer &) const;
RawBuffer receive(void) const;
- int getFd(void) const;
+
+ SockId getSockId(void) const noexcept;
+ int getFd(void) const noexcept;
const Credential &getCredential();
private:
namespace Csr {
-Dispatcher::Dispatcher(const std::string &path) : m_address(path)
+Dispatcher::Dispatcher(SockId sockId) : m_sockId(sockId)
{
}
void Dispatcher::connect()
{
- m_connection = std::make_shared<Connection>(Socket::connect(m_address));
+ m_connection = std::make_shared<Connection>(Socket::connect(m_sockId));
}
void Dispatcher::disconnect()
class Dispatcher {
public:
- Dispatcher(const std::string &path);
+ Dispatcher(SockId);
virtual ~Dispatcher();
Dispatcher(const Dispatcher &) = delete;
void connect(void);
void disconnect(void);
- std::string m_address;
+ SockId m_sockId;
ConnShPtr m_connection;
};
*/
#include "common/service.h"
+#include <utility>
#include <sys/types.h>
#include <sys/epoll.h>
namespace Csr {
-Service::Service(const std::string &address) : m_address(address)
+Service::Service()
{
- DEBUG("Service constructed with address[" << address << "]");
-
setNewConnectionCallback(nullptr);
setCloseConnectionCallback(nullptr);
}
{
}
+void Service::add(const SockId &id)
+{
+ m_sockIds.insert(id);
+}
+
void Service::start(int timeout)
{
INFO("Service start!");
- Socket socket(m_address);
+ for (const auto &id : m_sockIds) {
+ auto socket = std::make_shared<Socket>(id);
- DEBUG("Get systemd socket[" << socket.getFd()
- << "] with address[" << m_address << "]");
+ DEBUG("Get systemd socket[" << socket->getFd() <<
+ "] for sock id: " << static_cast<int>(id));
- m_loop.addEventSource(socket.getFd(), EPOLLIN | EPOLLHUP | EPOLLRDHUP,
- [&](uint32_t event) {
- if (event != EPOLLIN)
- return;
+ m_loop.addEventSource(socket->getFd(), EPOLLIN | EPOLLHUP | EPOLLRDHUP,
+ [this, socket](uint32_t event) {
+ if (event != EPOLLIN)
+ return;
- m_onNewConnection(std::make_shared<Connection>(socket.accept()));
- });
+ this->m_onNewConnection(std::make_shared<Connection>(socket->accept()));
+ });
+ }
m_loop.run(timeout);
}
-void Service::stop()
-{
- INFO("Service stop!");
-}
-
void Service::setNewConnectionCallback(const ConnCallback &/*callback*/)
{
/* TODO: scoped-lock */
#include <string>
#include <functional>
+#include <set>
#include "common/connection.h"
#include "common/mainloop.h"
+#include "common/socket-descriptor.h"
namespace Csr {
class Service {
public:
- Service(const std::string &address);
+ Service();
virtual ~Service();
Service(const Service &) = delete;
Service(Service &&) = delete;
Service &operator=(Service &&) = delete;
+ virtual void add(const SockId &) final;
virtual void start(int timeout) final;
- virtual void stop(void) final;
/* ConnCallback param should throw exception to handle error */
virtual void setNewConnectionCallback(const ConnCallback &) final;
std::unordered_map<int, ConnShPtr> m_connectionRegistry;
Mainloop m_loop;
- std::string m_address;
+
+ std::set<SockId> m_sockIds;
};
}
--- /dev/null
+/*
+ * Copyright (c) 2016 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 socket-descriptor.h
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief Socket path and privileges
+ */
+#include "common/socket-descriptor.h"
+
+#include <map>
+
+#include "common/exception.h"
+
+namespace Csr {
+
+namespace {
+
+const std::map<SockId, SocketDescriptor> g_sockDescMap {
+ {
+ SockId::CS,
+ SocketDescriptor("/tmp/." SERVICE_NAME "-cs.socket",
+ "http://tizen.org/privilege/antivirus.scan")
+ },
+ {
+ SockId::WP,
+ SocketDescriptor("/tmp/." SERVICE_NAME "-wp.socket",
+ "http://tizen.org/privilege/antivirus.webprotect")
+ },
+ {
+ SockId::ADMIN,
+ SocketDescriptor("/tmp/." SERVICE_NAME "-admin.socket",
+ "http://tizen.org/privilege/antivirus.admin")
+ },
+ {
+ SockId::POPUP,
+ SocketDescriptor("/tmp/." SERVICE_NAME "-popup.socket",
+ std::string())
+ }
+};
+
+} // namespace anonymous
+
+SocketDescriptor::SocketDescriptor(const std::string &_path, const std::string &_priv) :
+ path(_path), privilege(_priv) {}
+
+const SocketDescriptor &getSockDesc(const SockId &id)
+{
+ switch (id) {
+ case SockId::CS:
+ case SockId::WP:
+ case SockId::ADMIN:
+ case SockId::POPUP:
+ return g_sockDescMap.at(id);
+
+ default:
+ ThrowExc(InternalError, "Invalid sock id to descriptor map");
+ }
+}
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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 socket-descriptor.h
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief Socket path and privileges
+ */
+#pragma once
+
+#include <map>
+#include <string>
+
+namespace Csr {
+
+enum class SockId : int {
+ CS = 0x01, // Content scanning
+ WP = 0x02, // Web protection
+ ADMIN = 0x03, // Admin which controls engine
+ POPUP = 0x04, // Popup service
+};
+
+struct SocketDescriptor {
+ const std::string path;
+ const std::string privilege;
+
+ SocketDescriptor() {}
+ SocketDescriptor(const std::string &path, const std::string &priv);
+};
+
+const SocketDescriptor &getSockDesc(const SockId &);
+
+}
namespace {
+int g_sd_listen_fds = -1;
+
int createSystemdSocket(const std::string &path)
{
- int n = ::sd_listen_fds(-1);
+ if (g_sd_listen_fds == -1)
+ g_sd_listen_fds = ::sd_listen_fds(0);
- if (n < 0)
+ if (g_sd_listen_fds < 0)
ThrowExc(SocketError, "failed to sd_listen_fds");
- for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) {
+ for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + g_sd_listen_fds; ++fd) {
if (::sd_is_socket_unix(fd, SOCK_STREAM, 1, path.c_str(), 0) > 0) {
INFO("service's systemd socket found with fd: " << fd);
return fd;
}
}
- ThrowExc(SocketError, "get systemd socket failed!");
+ ThrowExc(SocketError, "No useable socket were passed by systemd. path: " << path);
}
} // namespace anonymous
-Socket::Socket(int fd) : m_fd(fd)
+Socket::Socket(SockId sockId, int fd) : m_sockId(sockId), m_fd(fd)
{
- if (m_fd < 0)
+ if (this->m_fd < 0)
ThrowExc(SocketError, "Socket fd from constructor is invalid!!");
}
-Socket::Socket(const std::string &path) : m_fd(createSystemdSocket(path))
+Socket::Socket(SockId sockId) : m_sockId(sockId)
{
+ this->m_fd = createSystemdSocket(getSockDesc(this->m_sockId).path);
}
-Socket::Socket(Socket &&other)
+Socket::Socket(Socket &&other) : m_sockId(other.m_sockId), m_fd(other.m_fd)
{
- m_fd = other.m_fd;
other.m_fd = 0;
}
if (this == &other)
return *this;
+ m_sockId = other.m_sockId;
m_fd = other.m_fd;
other.m_fd = 0;
::close(m_fd);
}
-Socket Socket::accept() const
+Socket Socket::accept(void) const
{
int fd = ::accept(m_fd, nullptr, nullptr);
if (fd < 0)
- ThrowExc(SocketError, "socket accept failed with errno: " << errno);
+ ThrowExc(SocketError, "socket on fd[" << m_fd << "] accept failed "
+ "with errno: " << errno);
INFO("Accept client success with fd: " << fd);
- return Socket(fd);
+ return Socket(m_sockId, fd);
}
-Socket Socket::connect(const std::string &path)
+Socket Socket::connect(SockId sockId)
{
+ const auto &path = getSockDesc(sockId).path;
+
if (path.size() >= sizeof(sockaddr_un::sun_path))
ThrowExc(InternalError, "socket path size too long!");
if (::connect(fd, reinterpret_cast<sockaddr *>(&addr),
sizeof(sockaddr_un)) == -1)
- ThrowExc(SocketError, "Socket connect failed with errno: " << errno);
+ ThrowExc(SocketError, "Socket[" << path << "] connect failed "
+ "with errno: " << errno);
INFO("Connect to CSR server success with fd:" << fd);
- return Socket(fd);
+ return Socket(sockId, fd);
+}
+
+SockId Socket::getSockId(void) const noexcept
+{
+ return m_sockId;
}
-int Socket::getFd() const
+int Socket::getFd(void) const noexcept
{
return m_fd;
}
#include <string>
#include "common/types.h"
+#include "common/socket-descriptor.h"
namespace Csr {
class Socket {
public:
- Socket(int fd = 0);
- Socket(const std::string &path); /* Construct with systemd socket from path */
+ // Socket with accepted / connected
+ Socket(SockId sockId, int fd);
+
+ // Create systemd socket
+ Socket(SockId sockId);
Socket(const Socket &) = delete;
Socket &operator=(const Socket &) = delete;
virtual ~Socket();
Socket accept(void) const;
- int getFd(void) const;
+
+ SockId getSockId(void) const noexcept;
+ int getFd(void) const noexcept;
RawBuffer read(void) const;
void write(const RawBuffer &data) const;
/* TODO: can it be constructor? */
- static Socket connect(const std::string &path);
+ static Socket connect(SockId);
private:
+ SockId m_sockId;
int m_fd;
};
try {
INFO("Start csr-server main!");
- Csr::ServerService service("/tmp/." SERVICE_NAME ".socket");
+ Csr::ServerService service;
INFO("Let's start csr-server service!");
namespace Csr {
-ServerService::ServerService(const std::string &address) :
- Service(address), m_workqueue(2, 10)
+ServerService::ServerService() : Service(), m_workqueue(2, 10)
{
+ this->add(SockId::CS);
+ this->add(SockId::WP);
+ this->add(SockId::ADMIN);
}
ServerService::~ServerService()
class ServerService : public Service {
public:
- ServerService(const std::string &address);
+ ServerService();
virtual ~ServerService();
private:
namespace Csr {
namespace Ui {
-AskUser::AskUser() : m_address("/tmp/." SERVICE_NAME "-popup.socket")
+AskUser::AskUser()
{
- m_dispatcher.reset(new Dispatcher(m_address));
+ m_dispatcher.reset(new Dispatcher(SockId::POPUP));
}
AskUser::~AskUser()
setlocale(LC_ALL, vconf_get_str(VCONFKEY_LANGSET));
- Csr::Ui::PopupService service("/tmp/." SERVICE_NAME "-popup.socket");
+ Csr::Ui::PopupService service;
// timeout when idle for 10 sec. If timeout time is too small and
// popup service wakes up repeatedly too quickly, it can be refused
} // namespace nonymous
-PopupService::PopupService(const std::string &address) : Service(address)
+PopupService::PopupService() : Service()
{
+ this->add(SockId::POPUP);
}
PopupService::~PopupService()
class PopupService : public Service {
public:
- PopupService(const std::string &address);
+ PopupService();
virtual ~PopupService();
private:
CONFIGURE_FILE(${SERVICE_NAME}.service.in ${SERVICE_NAME}.service @ONLY)
-CONFIGURE_FILE(${SERVICE_NAME}.socket.in ${SERVICE_NAME}.socket @ONLY)
+CONFIGURE_FILE(${SERVICE_NAME}-cs.socket.in ${SERVICE_NAME}-cs.socket @ONLY)
+CONFIGURE_FILE(${SERVICE_NAME}-wp.socket.in ${SERVICE_NAME}-wp.socket @ONLY)
+CONFIGURE_FILE(${SERVICE_NAME}-admin.socket.in ${SERVICE_NAME}-admin.socket @ONLY)
CONFIGURE_FILE(${SERVICE_NAME}-popup.service.in ${SERVICE_NAME}-popup.service @ONLY)
CONFIGURE_FILE(${SERVICE_NAME}-popup.socket.in ${SERVICE_NAME}-popup.socket @ONLY)
INSTALL(
FILES
${SERVICE_NAME}.service
- ${SERVICE_NAME}.socket
+ ${SERVICE_NAME}-cs.socket
+ ${SERVICE_NAME}-wp.socket
+ ${SERVICE_NAME}-admin.socket
${SERVICE_NAME}-popup.service
${SERVICE_NAME}-popup.socket
DESTINATION ${SYSTEMD_UNIT_DIR}
[Unit]
-Description=Csr framework socket
+Description=Csr admin socket
Wants=@SERVICE_NAME@.service
Before=@SERVICE_NAME@.service
[Socket]
-ListenStream=/tmp/.@SERVICE_NAME@.socket
+ListenStream=/tmp/.@SERVICE_NAME@-admin.socket
Service=@SERVICE_NAME@.service
SocketMode=0777
# smack access control on socket disabled shortly to fast development
-#SmackLabelIPIn=@SERVICE_NAME@::api
+#SmackLabelIPIn=@SERVICE_NAME@-admin::api
SmackLabelIPIn=*
SmackLabelIPOut=@
--- /dev/null
+[Unit]
+Description=Csr content screening socket
+Wants=@SERVICE_NAME@.service
+Before=@SERVICE_NAME@.service
+
+[Socket]
+ListenStream=/tmp/.@SERVICE_NAME@-cs.socket
+Service=@SERVICE_NAME@.service
+SocketMode=0777
+# smack access control on socket disabled shortly to fast development
+#SmackLabelIPIn=@SERVICE_NAME@-cs::api
+SmackLabelIPIn=*
+SmackLabelIPOut=@
+
+[Install]
+WantedBy=sockets.target
--- /dev/null
+[Unit]
+Description=Csr web protection socket
+Wants=@SERVICE_NAME@.service
+Before=@SERVICE_NAME@.service
+
+[Socket]
+ListenStream=/tmp/.@SERVICE_NAME@-wp.socket
+Service=@SERVICE_NAME@.service
+SocketMode=0777
+# smack access control on socket disabled shortly to fast development
+#SmackLabelIPIn=@SERVICE_NAME@-wp::api
+SmackLabelIPIn=*
+SmackLabelIPOut=@
+
+[Install]
+WantedBy=sockets.target
[Unit]
Description=Content Screening and Reputation service
-Requires=@SERVICE_NAME@.socket
+Requires=@SERVICE_NAME@-cs.socket @SERVICE_NAME@-wp.socket @SERVICE_NAME@-admin.socket
[Service]
User=@SERVICE_USER@
Group=@SERVICE_GROUP@
SmackProcessLabel=@SERVICE_NAME@
ExecStart=@BIN_DIR@/@SERVICE_NAME@-server
-Sockets=@SERVICE_NAME@.socket
+Sockets=@SERVICE_NAME@-cs.socket
+Sockets=@SERVICE_NAME@-wp.socket
+Sockets=@SERVICE_NAME@-admin.socket
[Install]
WantedBy=multi-user.target