SET(TARGET_DAEMON "device-certificate-managerd")
ADD_EXECUTABLE(${TARGET_DAEMON}
main.cpp
- dcmserver.cpp
- dcmsession.cpp
- serviceadapter.cpp
+ dcm_server.cpp
+ dcm_session.cpp
../shared/protobuf_asio.cpp
../shared/log.cpp
soresolver.cpp
/******************************************************************
*
- * Copyright 2019 Samsung Electronics All Rights Reserved.
+ * Copyright 2019 - 2020 Samsung Electronics All Rights Reserved.
*
* Author: Pawel Kowalski <p.kowalski2@partner.samsung.com>
*
API_DCM_BACKEND_EXPORT
int dcm_backend_request_certificate_chain(dcm_backend_context& ctx,
- std::string& mutable_chain);
+ std::string& chain);
API_DCM_BACKEND_EXPORT
int dcm_backend_sign_crypto_data(dcm_backend_context& ctx,
*
******************************************************************/
-#include "dcmserver.h"
-#include "dcmsession.h"
+#include <cynara-client.h>
+#include <systemd/sd-daemon.h>
+
+#include "dcm_server.h"
+#include "dcm_session.h"
#include "log.h"
-dcm_server::dcm_server(boost::asio::io_service& io_service, boost::asio::local::stream_protocol::acceptor&& acceptor, std::string lib_backend) :
- fService(io_service),
- fTimer(io_service),
- fAcceptor(std::move(acceptor)),
- fSoResolver(std::make_shared<so_resolver>(lib_backend))
+dcm_server::dcm_server(boost::asio::io_service& io_service,
+ boost::asio::local::stream_protocol::acceptor&& acceptor) :
+ fService(io_service),
+ fTimer(io_service),
+ fAcceptor(std::move(acceptor)),
+ fSoResolver(std::make_shared<so_resolver>())
{
LOGD("Construct server object");
+
+ cynara_configuration* cynara_conf = nullptr;
+ int error = cynara_configuration_create(&cynara_conf);
+ if(error != CYNARA_API_SUCCESS) {
+ LOGE("Can't initialize Cynara configuration: " << error);
+ throw std::runtime_error("Can't initialize Cynara configuration");
+ }
+
+ error = cynara_initialize(&fCynaraInstance, cynara_conf);
+ cynara_configuration_destroy(cynara_conf);
+ if(error != CYNARA_API_SUCCESS) {
+ LOGE("Can't initialize Cynara instance: " << error);
+ throw std::runtime_error("Can't initialize Cynara instance");
+ }
}
dcm_server::~dcm_server()
{
+ cynara_finish(fCynaraInstance);
LOGD("Destroy server object");
}
void dcm_server::start()
{
+ LOGD("Start server");
+ sd_listen_fds(1);
+ sd_notify(0, "READY=1");
do_accept();
}
std::shared_ptr<dcm_session> session;
try {
- session = std::make_shared<dcm_session>(fService, fTimer, shared_from_this(), fSoResolver);
+ session = std::make_shared<dcm_session>(fService, fTimer, shared_from_this(),
+ fSoResolver, fCynaraInstance, fSessionCounter);
} catch(std::bad_alloc& ex) {
LOGE("Out of memory when trying to allocate new session");
return;
/******************************************************************
*
- * Copyright 2017 - 2019 Samsung Electronics All Rights Reserved.
+ * Copyright 2017 - 2020 Samsung Electronics All Rights Reserved.
*
* Author: Jaroslaw Pelczar <j.pelczar@samsung.com>
*
*
******************************************************************/
-#ifndef DCM_DAEMON_DCMSERVER_H_
-#define DCM_DAEMON_DCMSERVER_H_
+#ifndef DCM_DAEMON_DCM_SERVER_H_
+#define DCM_DAEMON_DCM_SERVER_H_
+
+#include <memory>
#include <boost/asio.hpp>
#include <boost/noncopyable.hpp>
-#include <mutex>
-#include <memory>
+#include <cynara-client.h>
+
#include "soresolver.h"
class dcm_server final : public boost::noncopyable, public std::enable_shared_from_this<dcm_server> {
public:
- dcm_server(boost::asio::io_service& io_service, boost::asio::local::stream_protocol::acceptor&& acceptor, std::string lib_backend);
+ dcm_server(boost::asio::io_service& io_service,
+ boost::asio::local::stream_protocol::acceptor&& acceptor);
~dcm_server();
void start();
boost::asio::io_service& fService;
boost::asio::deadline_timer fTimer;
boost::asio::local::stream_protocol::acceptor fAcceptor;
- std::mutex fLock;
- std::shared_ptr<so_resolver> fSoResolver;
+ std::shared_ptr<so_resolver> fSoResolver;
+ cynara* fCynaraInstance;
+ unsigned int fSessionCounter = 0;
};
-#endif /* DCM_DAEMON_DCMSERVER_H_ */
+#endif /* DCM_DAEMON_DCM_SERVER_H_ */
#include <iostream>
#include <cassert>
-#include <map>
-#include <mutex>
#include <cynara-client.h>
#include <cynara-creds-socket.h>
#include <cynara-session.h>
-#include "dcmsession.h"
+#include "dcm_session.h"
+#include "dcm_server.h"
#include "log.h"
-#include "exception_translator.h"
-#include "dcmserver.h"
-
-extern cynara * gGlobalCynaraInstance;
-
-static inline std::string cynara_error_to_string(int error) {
- char buffer[256];
- int ret = cynara_strerror(error, buffer, sizeof(buffer));
- if(ret == CYNARA_API_SUCCESS)
- return std::string(buffer);
- return std::string("Can't translate error");
-}
-
-unsigned int globalSessionCounter = 0;
dcm_session::dcm_session(boost::asio::io_service& io_service,
- boost::asio::deadline_timer& timer,
- const std::shared_ptr<dcm_server>& server,
- std::shared_ptr<so_resolver> soResolver) :
- fService(io_service),
- fTimer(timer),
- fSocket(io_service),
- fServer(server),
- fSoResolver(soResolver)
+ boost::asio::deadline_timer& timer,
+ const std::shared_ptr<dcm_server>& server,
+ std::shared_ptr<so_resolver> soResolver,
+ cynara* cynaraInstance,
+ unsigned int& sessionCounter) :
+ fService(io_service),
+ fTimer(timer),
+ fSocket(io_service),
+ fServer(server),
+ fSoResolver(soResolver),
+ fCynaraInstance(cynaraInstance),
+ fSessionCounter(sessionCounter)
{
LOGD("Create new session object " << this);
- globalSessionCounter++;
+ fSessionCounter++;
}
dcm_session::~dcm_session()
LOGD("Destroy session object " << this);
}
-struct string_free_deleter {
- void operator()(char * p) const {
- free(p);
- }
-};
-
-bool dcm_session::verify_privileges(int handle)
-{
- int ret = 0;
- char * tmp_str;
- pid_t pid = 0;
-
- std::unique_ptr<char, string_free_deleter> user;
- std::unique_ptr<char, string_free_deleter> client;
- std::unique_ptr<char, string_free_deleter> client_session;
-
- /* Get user info */
- tmp_str = nullptr;
- ret = cynara_creds_socket_get_user(handle, USER_METHOD_DEFAULT, &tmp_str);
- if(ret != CYNARA_API_SUCCESS) {
- LOGE("Can't get user from socket : " << ret << " - " << cynara_error_to_string(ret));
- return false;
- }
- user.reset(tmp_str);
-
- /* Get client info */
- tmp_str = nullptr;
- ret = cynara_creds_socket_get_client(handle, CLIENT_METHOD_DEFAULT, &tmp_str);
- if(ret != CYNARA_API_SUCCESS) {
- LOGE("Can't get client from socket : " << ret << " - " << cynara_error_to_string(ret));
- return false;
- }
- client.reset(tmp_str);
-
-
- /* Get client PID from socket */
- ret = cynara_creds_socket_get_pid(handle, &pid);
- if(ret != CYNARA_API_SUCCESS) {
- LOGE("Can't get PID from socket : " << ret << " - " << cynara_error_to_string(ret));
- return false;
- }
-
- client_session.reset(cynara_session_from_pid(pid));
- if(!client_session) {
- LOGE("Can't get session identifier from PID");
- return false;
- }
-
- LOGD("Got new session from " << pid << " with user " << user.get() <<
- ", client ID " << client.get() << " and session ID " << client_session.get());
-
- ret = cynara_check(gGlobalCynaraInstance,
- client.get(),
- client_session.get(),
- user.get(),
- "http://tizen.org/privilege/devicecertificate");
-
- if(ret != CYNARA_API_ACCESS_ALLOWED) {
- LOGE("Application access denied for " << pid << " - " << cynara_error_to_string(ret));
- return false;
- }
-
- LOGD("Access granted for " << pid);
-
- return true;
-}
-
void dcm_session::start()
{
int handle = fSocket.native_handle();
void dcm_session::start_timer()
{
- globalSessionCounter--;
- LOGD("Number of active connections: " << globalSessionCounter);
+ fSessionCounter--;
+ LOGD("Number of active connections: " << fSessionCounter);
- if(globalSessionCounter == 0) {
+ if(fSessionCounter == 0) {
LOGD("No active connections, server will be closed after few seconds");
fTimer.expires_from_now(boost::posix_time::seconds(10));
/* operation_aborted error is returned whenever we cancel the timer or we reset the timer using expires_from_now function */
void dcm_session::stop_timer()
{
- globalSessionCounter++;
- LOGD("Number of active connections: " << globalSessionCounter);
+ fSessionCounter++;
+ LOGD("Number of active connections: " << fSessionCounter);
fTimer.cancel();
LOGD("Timer cancelled");
fDeserializer.read_message(fSocket,
[self, this](const boost::system::error_code& error, std::size_t bytes_read) {
- if(!error) {
- LOGD("Received " << bytes_read << " bytes from client");
- decode_message();
- } else {
- LOGE("Client disconnected: " << error);
- // Connection object will be released by shared ptr
- start_timer();
- }
+ if(!error) {
+ LOGD("Received " << bytes_read << " bytes from client");
+ decode_message();
+ } else {
+ LOGE("Client disconnected: " << error);
+ // Connection object will be released by shared ptr
+ start_timer();
+ }
});
} catch(std::exception& ex) {
LOGE("Caught exception while trying to read message : " << ex.what());
// Connection object will be released by shared ptr
- } catch(...) {
+ } catch(...) {
LOGE("Caught unknown exception while trying to read message");
// Connection object will be released by shared ptr
}
switch(requestMessage.request_oneof_case())
{
- case RequestMessage::kAssociateContext:
- handle_context_association(requestMessage.associate_context());
- break;
- case RequestMessage::kRequestChain:
- handle_cert_chain(requestMessage.request_chain());
- break;
- case RequestMessage::kSignData:
- handle_sign_request(requestMessage.sign_data());
- break;
- default:
- LOGE("Incorrect request message type");
- // This will terminate connection
- return;
+ case RequestMessage::kAssociateContext:
+ handle_context_association(requestMessage.associate_context());
+ break;
+ case RequestMessage::kRequestChain:
+ handle_cert_chain(requestMessage.request_chain());
+ break;
+ case RequestMessage::kSignData:
+ handle_sign_request(requestMessage.sign_data());
+ break;
+ default:
+ LOGE("Incorrect request message type");
+ // This will terminate connection
+ return;
}
} catch(std::exception& ex) {
LOGE("Caught exception while parsing message : " << ex.what());
fSerializer.encodeMessage(resp);
fSerializer.async_write(fSocket,
- [self, this](const boost::system::error_code& error, std::size_t bytes_written)
+ [self, this](const boost::system::error_code& error, std::size_t bytes_written)
{
if(!error) {
LOGD("Written " << bytes_written << " to socket");
}
}
+struct string_free_deleter {
+ void operator()(char * p) const {
+ free(p);
+ }
+};
+
+static inline std::string cynara_error_to_string(int error) {
+ char buffer[256];
+ int ret = cynara_strerror(error, buffer, sizeof(buffer));
+ if(ret == CYNARA_API_SUCCESS)
+ return std::string(buffer);
+ return std::string("Can't translate error");
+}
+
+bool dcm_session::verify_privileges(int handle)
+{
+ int ret = 0;
+ char* tmp_str;
+ pid_t pid = 0;
+
+ std::unique_ptr<char, string_free_deleter> user;
+ std::unique_ptr<char, string_free_deleter> client;
+ std::unique_ptr<char, string_free_deleter> client_session;
+
+ /* Get user info */
+ tmp_str = nullptr;
+ ret = cynara_creds_socket_get_user(handle, USER_METHOD_DEFAULT, &tmp_str);
+ if(ret != CYNARA_API_SUCCESS) {
+ LOGE("Can't get user from socket : " << ret << " - " << cynara_error_to_string(ret));
+ return false;
+ }
+ user.reset(tmp_str);
+
+ /* Get client info */
+ tmp_str = nullptr;
+ ret = cynara_creds_socket_get_client(handle, CLIENT_METHOD_DEFAULT, &tmp_str);
+ if(ret != CYNARA_API_SUCCESS) {
+ LOGE("Can't get client from socket : " << ret << " - " << cynara_error_to_string(ret));
+ return false;
+ }
+ client.reset(tmp_str);
+
+ /* Get client PID from socket */
+ ret = cynara_creds_socket_get_pid(handle, &pid);
+ if(ret != CYNARA_API_SUCCESS) {
+ LOGE("Can't get PID from socket : " << ret << " - " << cynara_error_to_string(ret));
+ return false;
+ }
+
+ client_session.reset(cynara_session_from_pid(pid));
+ if(!client_session) {
+ LOGE("Can't get session identifier from PID");
+ return false;
+ }
+
+ LOGD("Got new session from " << pid << " with user " << user.get() <<
+ ", client ID " << client.get() << " and session ID " << client_session.get());
+
+ ret = cynara_check(fCynaraInstance, client.get(), client_session.get(), user.get(),
+ "http://tizen.org/privilege/devicecertificate");
+
+ if(ret != CYNARA_API_ACCESS_ALLOWED) {
+ LOGE("Application access denied for " << pid << " - " << cynara_error_to_string(ret));
+ return false;
+ }
+
+ LOGD("Access granted for " << pid);
+ return true;
+}
+
void dcm_session::handle_context_association(const AssociateKeyContext& message)
{
LOGD("Associate context");
ResponseMessage msg;
- auto * contextResponse = msg.mutable_associate_context();
+ auto* contextResponse = msg.mutable_associate_context();
if(fBackendContext) {
contextResponse->set_result(EEXIST);
" with usage " << message.usage() << " and key type " << message.key_type());
auto server = fServer.lock();
-
if(!server) {
LOGE("Server object gone while handling message");
return;
}
- int error = run_with_exception_handler([&]() {
-
- bool loaded = fSoResolver->ensure_loaded();
- if (loaded) {
- fBackendContext = std::unique_ptr<dcm_backend_context>(new dcm_backend_context);
-
- fSoResolver->invoke<void, dcm_backend_context&, const std::string&>(
- "dcm_backend_create_key_context",
- *fBackendContext,
- message.key_type()
- );
-
- CryptoKeyType crypto_key_type = fSoResolver->invoke<CryptoKeyType, dcm_backend_context&>(
- "dcm_backend_key_type",
- *fBackendContext
- );
- contextResponse->set_key_type(crypto_key_type);
-
- unsigned int crypto_key_length = fSoResolver->invoke<unsigned int, dcm_backend_context&>(
- "dcm_backend_key_length",
- *fBackendContext
- );
- contextResponse->set_key_length(crypto_key_length);
- }
- else {
- LOGE("No usable backend available");
- throw std::invalid_argument("Unable to find backend");
- }
+ int error = 0;
+ try {
+ fBackendContext = std::unique_ptr<dcm_backend_context>(new dcm_backend_context);
+
+ fSoResolver->invoke<void, dcm_backend_context&, const std::string&>(
+ "dcm_backend_create_key_context", *fBackendContext, message.key_type());
+
+ CryptoKeyType crypto_key_type = fSoResolver->invoke<CryptoKeyType, dcm_backend_context&>(
+ "dcm_backend_key_type", *fBackendContext);
+ contextResponse->set_key_type(crypto_key_type);
+
+ unsigned int crypto_key_length = fSoResolver->invoke<unsigned int, dcm_backend_context&>(
+ "dcm_backend_key_length", *fBackendContext);
+ contextResponse->set_key_length(crypto_key_length);
+
fCookie = (uintptr_t)fBackendContext.get();
contextResponse->set_context_cookie(fCookie);
- });
+ } catch(std::bad_alloc&) {
+ error = -ENOMEM;
+ } catch(std::exception&) {
+ error = -EINVAL;
+ } catch(...) {
+ error = -EFAULT;
+ }
contextResponse->set_result(error);
-
reply(msg);
}
void dcm_session::handle_cert_chain(const RequestCertificateChain& message)
{
- ResponseMessage msg;
- auto * certificateResponse = msg.mutable_request_chain();
-
LOGD("Request certificate chain");
+ ResponseMessage msg;
+ auto* certificateResponse = msg.mutable_request_chain();
+
if(message.context_cookie() != fCookie) {
LOGE("Received unknown context cookie");
certificateResponse->set_result(-EINVAL);
std::string cert_chain;
- int error = 0;
- bool loaded = fSoResolver->ensure_loaded();
- if (loaded) {
- error = fSoResolver->invoke<int, dcm_backend_context&, std::string&>(
- "dcm_backend_request_certificate_chain",
- *fBackendContext,
- cert_chain
- );
- }
+ int error = fSoResolver->invoke<int, dcm_backend_context&, std::string&>(
+ "dcm_backend_request_certificate_chain", *fBackendContext, cert_chain);
if(error != 0) {
certificateResponse->set_result(error);
}
if(cert_chain.length() >= sPEMHeader.length() &&
- !memcmp(sPEMHeader.c_str(), cert_chain.c_str(), sPEMHeader.size()) &&
- cert_chain[cert_chain.size() - 1] != '\0')
+ !memcmp(sPEMHeader.c_str(), cert_chain.c_str(), sPEMHeader.size()) &&
+ cert_chain[cert_chain.size() - 1] != '\0')
{
// Add missing 0
cert_chain.push_back(0);
LOGD("Request data signing");
ResponseMessage msg;
- auto * signingResponse = msg.mutable_sign_data();
+ auto* signingResponse = msg.mutable_sign_data();
if(message.context_cookie() != fCookie) {
LOGE("Received unknown context cookie");
}
if(message.data_to_sign().size() == 0) {
- LOGE("Data to sign is empty and hash type is NONE");
+ LOGE("Data to sign is empty");
signingResponse->set_result(-EINVAL);
return;
}
- int error = 0;
- bool loaded = fSoResolver->ensure_loaded();
- if (loaded) {
- error = fSoResolver->invoke<int, dcm_backend_context&, MessageDigestType, const std::string&, std::string&>(
- "dcm_backend_sign_crypto_data",
- *fBackendContext,
- message.digest_type(),
- message.data_to_sign(),
- *signingResponse->mutable_signature()
- );
- }
- signingResponse->set_result(error);
+ int error = fSoResolver->invoke<int, dcm_backend_context&, MessageDigestType, const std::string&, std::string&>(
+ "dcm_backend_sign_crypto_data", *fBackendContext, message.digest_type(), message.data_to_sign(), *signingResponse->mutable_signature());
+ signingResponse->set_result(error);
reply(msg);
}
/******************************************************************
*
- * Copyright 2017 - 2019 Samsung Electronics All Rights Reserved.
+ * Copyright 2017 - 2020 Samsung Electronics All Rights Reserved.
*
* Author: Jaroslaw Pelczar <j.pelczar@samsung.com>
*
*
******************************************************************/
-#ifndef DCM_DAEMON_DCMSESSION_H_
-#define DCM_DAEMON_DCMSESSION_H_
+#ifndef DCM_DAEMON_DCM_SESSION_H_
+#define DCM_DAEMON_DCM_SESSION_H_
#include <memory>
+
#include <boost/asio.hpp>
#include <boost/noncopyable.hpp>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
#include "dcm_support.pb.h"
#include "protobuf_asio.h"
#include "dcm-backend-api.h"
#include "soresolver.h"
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-
class dcm_server;
-class dcm_session final : public std::enable_shared_from_this<dcm_session>,
- public boost::noncopyable
+class dcm_session final : public std::enable_shared_from_this<dcm_session>, public boost::noncopyable
{
public:
- dcm_session(boost::asio::io_service& io_service, boost::asio::deadline_timer& timer, const std::shared_ptr<dcm_server>& server, std::shared_ptr<so_resolver> soResolver);
+ dcm_session(boost::asio::io_service& io_service,
+ boost::asio::deadline_timer& timer,
+ const std::shared_ptr<dcm_server>& server,
+ std::shared_ptr<so_resolver> soResolver,
+ cynara* cynaraInstance,
+ unsigned int& sessionCounter);
~dcm_session();
void start();
protobuf_async_message_deserialization fDeserializer;
std::weak_ptr<dcm_server> fServer;
std::shared_ptr<dcm_backend_context> fBackendContext;
- std::shared_ptr<so_resolver> fSoResolver;
+ std::shared_ptr<so_resolver> fSoResolver;
uint64_t fCookie = 0;
+ cynara* fCynaraInstance;
+ unsigned int& fSessionCounter;
};
-#endif /* DCM_DAEMON_DCMSESSION_H_ */
+#endif /* DCM_DAEMON_DCM_SESSION_H_ */
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2017 Samsung Electronics All Rights Reserved.
- *
- * Author: Jaroslaw Pelczar <j.pelczar@samsung.com>
- *
- * 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.
- *
- ******************************************************************/
-
-#ifndef DCM_DAEMON_EXCEPTION_TRANSLATOR_H_
-#define DCM_DAEMON_EXCEPTION_TRANSLATOR_H_
-
-#include <memory>
-#include <stdexcept>
-#include <cerrno>
-#include <boost/system/system_error.hpp>
-
-template<typename T> inline int run_with_exception_handler(T t) {
- try {
- t();
- } catch(boost::system::system_error& ex) {
- return -ex.code().value();
- } catch(std::bad_alloc&) {
- return -ENOMEM;
- } catch(std::domain_error&) {
- return -EDOM;
- } catch(std::invalid_argument&) {
- return -EINVAL;
- } catch(std::length_error&) {
- return -EINVAL;
- } catch(std::out_of_range&) {
- return -EINVAL;
- } catch(std::range_error&) {
- return -ERANGE;
- } catch(std::overflow_error&) {
- return -EOVERFLOW;
- } catch(std::underflow_error&) {
- return -EOVERFLOW;
- } catch(std::exception&) {
- return -EINVAL;
- } catch(...) {
- return -EFAULT;
- }
-
- return 0;
-}
-
-#endif /* DCM_DAEMON_EXCEPTION_TRANSLATOR_H_ */
#include <sys/signal.h>
#include <boost/asio.hpp>
-#include <cynara-client.h>
+#include <systemd/sd-daemon.h>
-#include "dcmserver.h"
+#include "dcm_server.h"
#include "log.h"
-#include "serviceadapter.h"
-cynara * gGlobalCynaraInstance;
-
-int main()
+boost::asio::local::stream_protocol::acceptor socket_acceptor(boost::asio::io_service& io_service)
{
- int error = 0;
- service_adapter serviceAdapter;
-
- cynara_configuration * cynara_conf = nullptr;
- error = cynara_configuration_create(&cynara_conf);
- if(error != CYNARA_API_SUCCESS) {
- LOGE("Can't initialize Cynara configuration: " << error);
- serviceAdapter.notify_start_failure(error);
- return EXIT_FAILURE;
+ LOGD("Try to get socket from systemd");
+ int n = sd_listen_fds(0);
+ if(n > 0) {
+ for(int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) {
+ if(sd_is_socket_unix(fd, SOCK_STREAM, 1, DCM_UNIX_SOCKET_PATH, 0)) {
+ LOGD("Got UNIX domain socket with fd " << fd);
+ return boost::asio::local::stream_protocol::acceptor(
+ io_service, boost::asio::local::stream_protocol(), fd);
+ }
+ }
}
- error = cynara_initialize(&gGlobalCynaraInstance, cynara_conf);
+ LOGE("No systemd sockets found");
+ throw std::runtime_error("No socket created by systemd");
+}
- cynara_configuration_destroy(cynara_conf);
+int main()
+{
+ try {
+ /* Change the file mode mask */
+ (void)umask(0);
- if(error != CYNARA_API_SUCCESS) {
- LOGE("Can't initialize Cynara instance: " << error);
- serviceAdapter.notify_start_failure(error);
- return EXIT_FAILURE;
- }
+ /* Use root directory as working directory */
+ int error = chdir("/");
+ (void)error;
- try {
boost::asio::io_service io_service;
-
- /* Catch signals */
boost::asio::signal_set stop_signals(io_service, SIGINT, SIGTERM);
-
stop_signals.async_wait([&io_service](const boost::system::error_code&, int sig) {
LOGD("Stopped by signal " << sig);
io_service.stop();
});
- /* Change the file mode mask */
- (void)umask(0);
-
- /* Use root directory as working directory */
- error = chdir("/");
- (void)error; // Don't care
-
- std::string lib_backend = "libdcm-backend-api.so.1.0";
- auto server(std::make_shared<dcm_server>(io_service, serviceAdapter.create_platform_socket_acceptor(io_service), lib_backend));
+ auto server(std::make_shared<dcm_server>(io_service, socket_acceptor(io_service)));
boost::asio::signal_set hup_signals(io_service, SIGHUP);
-
hup_signals.async_wait([](const boost::system::error_code&, int) {
LOGD("Received HUP signal");
});
-
- serviceAdapter.notify_start_complete();
-
- LOGD("Start server");
-
server->start();
io_service.run();
} catch(std::bad_alloc& e) {
- serviceAdapter.notify_start_failure(ENOMEM);
LOGE("Server failed with OOM exception: " << e.what());
- return EXIT_FAILURE;
+ return EXIT_FAILURE;
} catch(std::exception& e) {
- serviceAdapter.notify_start_failure(EFAULT);
LOGE("Server failed with exception: " << e.what());
return EXIT_FAILURE;
} catch(...) {
LOGE("Server failed with unknown exception");
- serviceAdapter.notify_start_failure(EFAULT);
return EXIT_FAILURE;
}
- cynara_finish(gGlobalCynaraInstance);
- gGlobalCynaraInstance = nullptr;
-
LOGD("Server terminated");
-
return 0;
}
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2017 - 2020 Samsung Electronics All Rights Reserved.
- *
- * Author: Jaroslaw Pelczar <j.pelczar@samsung.com>
- *
- * 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.
- *
- ******************************************************************/
-
-#include <cstring>
-
-#include <systemd/sd-daemon.h>
-
-#include "serviceadapter.h"
-#include "log.h"
-
-service_adapter::service_adapter()
-{
-}
-
-service_adapter::~service_adapter()
-{
-}
-
-boost::asio::local::stream_protocol::acceptor service_adapter::create_platform_socket_acceptor(boost::asio::io_service& io_service)
-{
- LOGD("Try to get socket from systemd");
-
- int n = sd_listen_fds(0);
- if( n > 0 ) {
- for(int fd = SD_LISTEN_FDS_START ; fd < SD_LISTEN_FDS_START + n ; ++fd) {
- if(sd_is_socket_unix(fd, SOCK_STREAM, 1, fDefaultSocketPath.c_str(), 0)) {
- LOGD("Got UNIX domain socket with fd " << fd);
-
- return boost::asio::local::stream_protocol::acceptor(
- io_service,
- boost::asio::local::stream_protocol(),
- fd);
- }
- }
- }
-
- LOGE("No systemd sockets found");
-
- throw std::runtime_error("No socket created by systemd");
-}
-
-void service_adapter::notify_start_complete()
-{
- LOGD("Notify start completed to systemd");
-
- sd_listen_fds(1);
- sd_notify(0, "READY=1");
- fStartCompleteNotified = true;
-}
-
-void service_adapter::notify_start_failure(int error)
-{
- LOGE("Notify start failure");
-
- if(!fStartCompleteNotified) {
- char buffer[512];
- buffer[0] = '\0';
- if(!strerror_r(error, buffer, sizeof(buffer)))
- sd_notifyf(0, "STATUS=Failed to start up: %s\nERRNO=%d", buffer, error);
- else
- sd_notifyf(0, "STATUS=Failed to start up: (no message)\nERRNO=%d", error);
- }
-}
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2017 - 2020 Samsung Electronics All Rights Reserved.
- *
- * Author: Jaroslaw Pelczar <j.pelczar@samsung.com>
- *
- * 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.
- *
- ******************************************************************/
-
-#ifndef DCM_DAEMON_SERVICEADAPTER_H_
-#define DCM_DAEMON_SERVICEADAPTER_H_
-
-#include <boost/noncopyable.hpp>
-#include <boost/asio.hpp>
-
-class service_adapter final : public boost::noncopyable {
-public:
- service_adapter();
- ~service_adapter();
-
- boost::asio::local::stream_protocol::acceptor create_platform_socket_acceptor(boost::asio::io_service& io_service);
-
- void notify_start_complete();
- void notify_start_failure(int error);
-
-private:
- std::string fDefaultSocketPath = DCM_UNIX_SOCKET_PATH;
- bool fStartCompleteNotified = false;
-};
-
-#endif /* DCM_DAEMON_SERVICEADAPTER_H_ */
#include "soresolver.h"
#include "log.h"
-so_resolver::so_resolver(const std::string& libraryName) :
- fLibraryName(libraryName),
- fLibraryHandle(nullptr)
+so_resolver::so_resolver()
{
-}
-
-so_resolver::~so_resolver()
-{
- if(fLibraryHandle.load(std::memory_order_relaxed)) {
- LOGD("Unloading library " << fLibraryName);
- dlclose(fLibraryHandle.exchange(nullptr, std::memory_order_relaxed));
- LOGD("Unloaded library " << fLibraryName);
- }
-}
-
-void * so_resolver::resolve_function(const std::string& name) noexcept
-{
- std::unique_lock<std::mutex> locker(fCacheLock);
- auto it = fCache.find(name);
-
- if(it != fCache.end())
- return it->second;
-
- void * handle = fLibraryHandle.load(std::memory_order_relaxed);
-
- if(handle) {
- LOGD("Resolving symbol " << name << " from " << fLibraryName);
- void * sym = dlsym(handle, name.c_str());
- if(!sym) {
- LOGE("Unable to resolve symbol " << name << " from " <<
- fLibraryName << ": Error is " << dlerror());
- } else {
- try {
- fCache.emplace(name, sym);
- } catch(...) {
- }
- }
- return sym;
- }
-
- LOGE("Trying to resolve symbol " << name << " from not loaded library " << fLibraryName);
-
- return nullptr;
-}
-
-bool so_resolver::ensure_loaded() noexcept
-{
- std::unique_lock<std::mutex> locker(fCacheLock);
-
- void * handle = fLibraryHandle.load(std::memory_order_acquire);
-
- if(handle)
- return true;
-
LOGD("Loading library " << fLibraryName);
- handle = dlopen(fLibraryName.c_str(), RTLD_LAZY | RTLD_LOCAL);
-
- if(!handle) {
+ fLibraryHandle = dlopen(fLibraryName.c_str(), RTLD_LAZY | RTLD_LOCAL);
+ if(!fLibraryHandle) {
LOGE("Unable to load library " << fLibraryName << ": " << dlerror());
- return false;
+ throw std::runtime_error("Unable to load backend");
}
LOGD("Library loaded " << fLibraryName);
+}
- void * expectedValue = nullptr;
+so_resolver::~so_resolver()
+{
+ LOGD("Unloading library " << fLibraryName);
+ dlclose(fLibraryHandle);
+ LOGD("Unloaded library " << fLibraryName);
+}
- if(!fLibraryHandle.compare_exchange_strong(expectedValue, handle, std::memory_order_release)) {
- // Someone else have opened the library
- dlclose(handle);
+void* so_resolver::resolve_function(const std::string& name) noexcept
+{
+ LOGD("Resolving symbol " << name << " from " << fLibraryName);
+ void* sym = dlsym(fLibraryHandle, name.c_str());
+ if(!sym) {
+ LOGE("Unable to resolve symbol " << name << " from " << fLibraryName << ": Error is " << dlerror());
}
-
- return true;
+ return sym;
}
/******************************************************************
*
- * Copyright 2017 - 2019 Samsung Electronics All Rights Reserved.
+ * Copyright 2017 - 2020 Samsung Electronics All Rights Reserved.
*
* Author: Jaroslaw Pelczar <j.pelczar@samsung.com>
*
#ifndef DCM_DAEMON_SORESOLVER_H_
#define DCM_DAEMON_SORESOLVER_H_
-#include <boost/noncopyable.hpp>
#include <string>
-#include <atomic>
#include <stdexcept>
-#include <map>
-#include <mutex>
-#include <string>
+
+#include <boost/noncopyable.hpp>
+
+#define DCM_BACKEND "libdcm-backend-api.so.1.0"
class so_resolver : public boost::noncopyable {
public:
- so_resolver(const std::string& libraryName);
+ so_resolver();
~so_resolver();
- bool ensure_loaded() noexcept;
- void * resolve_function(const std::string& name) noexcept;
+ void* resolve_function(const std::string& name) noexcept;
- template<typename ReturnValue, typename... Args> ReturnValue invoke(const std::string& name, Args... args) {
+ template<typename ReturnValue, typename... Args> ReturnValue invoke(const std::string& name, Args... args) {
typedef ReturnValue (* function_t)(Args...);
function_t func = (function_t)resolve_function(name);
if(!func) {
}
private:
- std::string fLibraryName;
- std::atomic<void *> fLibraryHandle;
- std::mutex fCacheLock;
- std::map<std::string, void *> fCache;
+ std::string fLibraryName = DCM_BACKEND;
+ void* fLibraryHandle = nullptr;
};
#endif /* DCM_DAEMON_SORESOLVER_H_ */