#include "espp_service_priv.h"
#include <stdio.h>
-#include <stdbool.h>
#include <getopt.h>
-#include <glib.h>
#include <sys/stat.h>
static struct sigaction g_int_old_action;
static struct sigaction g_sys_old_action;
static struct sigaction g_xcpu_old_action;
-typedef struct {
- bool start_service;
- GMainLoop *mainloop;
-} espp_service_s;
+espp_service_s *g_svc;
static void print_usage()
{
sigfillset(&all_mask);
sigprocmask(SIG_BLOCK, &all_mask, &old_mask);
- /* TODO: release resources */
+ espp_service_deinit_socket(g_svc);
sigprocmask(SIG_SETMASK, &old_mask, NULL);
/* signal unblock ------------ */
int main(int argc, char *argv[])
{
- espp_service_s svc = { false, NULL };
+ espp_service_s svc = { false, NULL, -1, 0 };
- LOG_INFO("LAUNCH, version[%s]", ESPP_SVC_VERSION);
+ LOG_WARNING("launched, version[%s]", ESPP_SVC_VERSION);
if (get_option(argc, argv, &svc))
return 1;
goto exit;
}
+ g_svc = &svc;
+
initialize_signals();
signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE */
umask(0); /* change the file mode mask */
- /* TODO: init socket */
+ if (espp_service_init_socket(&svc) != 0)
+ goto exit;
run(&svc);
- /* TODO: release socket */
+ espp_service_deinit_socket(&svc);
deinitialize_signals();
exit:
- LOG_INFO("EXIT");
+ LOG_WARNING("exit");
return 0;
}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.
+ */
+
+#include "espp_service_priv.h"
+#include <stdint.h>
+#include <gio/gio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <pthread.h>
+
+#define ESPP_SERVICE_SOCK "/run/espp_service.socket"
+#define MAX_ERROR_LEN 64
+#define MAX_FUNC_LEN 32
+
+typedef struct {
+ char func[MAX_FUNC_LEN];
+} espp_service_data_from_client_s;
+
+typedef struct {
+ int ret;
+} espp_service_data_from_server_s;
+
+static void *__work_thread_func(void *data)
+{
+ int fd;
+ int ret;
+ char str_error[MAX_ERROR_LEN] = {'\0',};
+ espp_service_data_from_client_s rx_data;
+ espp_service_data_from_server_s tx_data;
+
+ ASSERT(data);
+
+ fd = (int)(uintptr_t)(data);
+ ASSERT(fd != -1);
+
+ do {
+ memset(&rx_data, 0x00, sizeof(espp_service_data_from_client_s));
+ if ((ret = read(fd, &rx_data, sizeof(espp_service_data_from_client_s))) < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ LOG_ERROR("failed to read(), fd[%d], err: %s", fd, str_error);
+
+ } else if (ret == sizeof(espp_service_data_from_client_s)) {
+
+ LOG_DEBUG("<<<<< from fd[%d]: func[%s]", fd, rx_data.func);
+
+ memset(&tx_data, 0x00, sizeof(espp_service_data_from_server_s));
+
+ /* TODO: add handler */
+ tx_data.ret = 0;
+
+ LOG_DEBUG(">>>>>> to fd[%d]: ret[%d]", fd, tx_data.ret);
+
+ if (write(fd, &tx_data, sizeof(espp_service_data_from_server_s)) < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ LOG_ERROR("failed to write(), fd[%d], err: %s", fd, str_error);
+ }
+
+ /* TODO: exit condition from command */
+ goto exit;
+
+ } else {
+ LOG_ERROR("failed to read(), fd[%d], read size mismatched: ret[%d], expect size[%zu]",
+ fd, ret, sizeof(espp_service_data_from_client_s));
+ goto exit;
+ }
+ } while (1);
+
+exit:
+ LOG_DEBUG("close fd[%d]", fd);
+ close(fd);
+ pthread_exit(NULL);
+}
+
+static void *__listen_thread_func(void *data)
+{
+ espp_service_s *svc = (espp_service_s *)data;
+ int ret;
+ int fd;
+ int client_fd = -1;
+ pthread_attr_t attr;
+ char str_error[MAX_ERROR_LEN] = {'\0',};
+
+ pthread_t work_thread_id;
+
+ ASSERT(svc);
+ ASSERT(svc->fd >= 0);
+
+ ret = pthread_attr_init(&attr);
+ if (ret != 0) {
+ LOG_ERROR("failed to pthread_attr_init(), ret[%d]", ret);
+ goto exit;
+ }
+
+ ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ if (ret != 0) {
+ LOG_ERROR("failed to pthread_attr_setdetachstate(), ret[%d]", ret);
+ goto exit;
+ }
+
+ fd = svc->fd;
+
+ if (listen(fd, 5)) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ LOG_ERROR("failed to listen(), err: %s", str_error);
+ goto exit;
+ }
+ LOG_INFO("listen for fd[%d] success", fd);
+
+ do {
+ client_fd = accept(fd, NULL, NULL);
+ if (client_fd == -1) {
+ if (errno == EINVAL) /* this might be for socket close */
+ goto exit;
+ strerror_r(errno, str_error, sizeof(str_error));
+ LOG_ERROR("failed to accept(), err: %s", str_error);
+ goto exit;
+ }
+ LOG_DEBUG("client_fd[%d]", client_fd);
+
+ if (pthread_create(&work_thread_id, &attr, (void *)__work_thread_func, (void *)(uintptr_t)client_fd)) {
+ LOG_ERROR("failed to pthread_create(), client_fd[%d]", client_fd);
+ goto exit;
+ }
+
+ } while (1);
+
+exit:
+ if (client_fd >= 0)
+ close(client_fd);
+
+ LOG_DEBUG("pthread_exit()");
+ pthread_attr_destroy(&attr);
+ pthread_exit(NULL);
+}
+
+static int __create_listener_thread(espp_service_s *svc)
+{
+ ASSERT(svc);
+ ASSERT(svc->fd >= 0);
+
+ if (pthread_create(&svc->thread_id, NULL, (void *)__listen_thread_func, (void *)svc)) {
+ LOG_ERROR("failed to pthread_create()");
+ return -1;
+ }
+
+ LOG_DEBUG("thread_id[0x%x]", (unsigned)svc->thread_id);
+
+ return 0;
+}
+
+int espp_service_init_socket(espp_service_s *svc)
+{
+ int fd;
+ struct sockaddr_un addr_un;
+ char str_error[128] = {'\0',};
+
+ ASSERT(svc);
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ LOG_ERROR("failed to socket(), err: %s", str_error);
+ goto exit;
+ }
+
+ LOG_DEBUG("fd[%d]", fd);
+
+ memset(&addr_un, 0, sizeof(addr_un));
+ addr_un.sun_family = AF_UNIX;
+ strncpy(addr_un.sun_path, ESPP_SERVICE_SOCK, sizeof(addr_un.sun_path));
+
+ if (bind(fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
+ int errsv = errno;
+ strerror_r(errsv, str_error, sizeof(str_error));
+ LOG_ERROR("failed to bind(), err: %s", str_error);
+ if (errsv == EADDRINUSE) {
+ unlink(ESPP_SERVICE_SOCK);
+ LOG_DEBUG("unlink socket and bind again...");
+ if (bind(fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ LOG_ERROR("failed to bind() again, err: %s", str_error);
+ goto exit;
+ }
+ } else {
+ goto exit;
+ }
+ }
+
+ svc->fd = fd;
+ LOG_DEBUG("socket binding success, fd[%d]", svc->fd);
+
+ if (__create_listener_thread(svc) != 0)
+ goto exit;
+
+ return 0;
+
+exit:
+ if (fd >= 0)
+ close(fd);
+
+ return -1;
+}
+
+void espp_service_deinit_socket(espp_service_s *svc)
+{
+ ASSERT(svc);
+
+ if (svc->fd >= 0) {
+ unlink(ESPP_SERVICE_SOCK);
+ shutdown(svc->fd, SHUT_RDWR);
+ close(svc->fd);
+ LOG_DEBUG("close() done, fd[%d]", svc->fd);
+ svc->fd = -1;
+ }
+
+ if (svc->thread_id > 0) {
+ LOG_DEBUG("try to pthread_join(), thread_id[0x%x]", (unsigned)svc->thread_id);
+ pthread_join(svc->thread_id, NULL);
+ LOG_DEBUG("pthread_join() done");
+ svc->thread_id = 0;
+ }
+}
\ No newline at end of file