Add liblaunchpad-common library for launchpad daemons 44/289444/9
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 9 Mar 2023 05:03:33 +0000 (05:03 +0000)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 9 Mar 2023 06:04:54 +0000 (06:04 +0000)
The liblaunchpad-common library is added for launchpad daemons.

Change-Id: I4cc7d88a3709184a6cfd3908160d23c044341648
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
15 files changed:
CMakeLists.txt
packaging/launchpad.spec
src/launchpad-process-pool/CMakeLists.txt
src/lib/CMakeLists.txt
src/lib/launchpad-common/CMakeLists.txt [new file with mode: 0644]
src/lib/launchpad-common/client_socket.cc [new file with mode: 0644]
src/lib/launchpad-common/client_socket.hh [new file with mode: 0644]
src/lib/launchpad-common/exception.cc [new file with mode: 0644]
src/lib/launchpad-common/exception.hh [new file with mode: 0644]
src/lib/launchpad-common/io_channel.cc [new file with mode: 0644]
src/lib/launchpad-common/io_channel.hh [new file with mode: 0644]
src/lib/launchpad-common/log_private.hh [new file with mode: 0644]
src/lib/launchpad-common/pkgconfig/liblaunchpad-common.pc.in [new file with mode: 0644]
src/lib/launchpad-common/server_socket.cc [new file with mode: 0644]
src/lib/launchpad-common/server_socket.hh [new file with mode: 0644]

index fb3253d..cccc039 100644 (file)
@@ -36,6 +36,7 @@ SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
 ## Targets
 SET(TARGET_APP_DEFINED_LOADER "app-defined-loader")
 SET(TARGET_LAUNCHPAD "launchpad")
+SET(TARGET_LAUNCHPAD_COMMON "launchpad-common")
 SET(TARGET_LAUNCHPAD_HYDRA "launchpad-hydra")
 SET(TARGET_LAUNCHPAD_LOADER "launchpad-loader")
 SET(TARGET_LAUNCHPAD_PARSER "launchpad-parser")
index 13dcb12..116fdc0 100644 (file)
@@ -179,11 +179,15 @@ ln -sf ../launchpad-process-pool.service %{buildroot}%{_unitdir_user}/basic.targ
 %{_prefix}/share/aul/launchpad.conf
 %{_sysconfdir}/package-manager/parserlib/liblaunchpad-parser.so
 %{_datadir}/parser-plugins/*
+%attr(0644,root,root) %{_libdir}/liblaunchpad-common.so.*
 
 %files devel
 %{_includedir}/launchpad/*.h
+%{_includedir}/launchpad-common/*.hh
 %{_libdir}/*.so
 %{_libdir}/pkgconfig/launchpad.pc
+%attr(0644,root,root) %{_libdir}/liblaunchpad-common.so
+%{_libdir}/pkgconfig/liblaunchpad-common.pc
 
 %files -n launchpad-loader
 %manifest launchpad-loader.manifest
index e619fe3..7440026 100644 (file)
@@ -42,7 +42,8 @@ APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC
   VCONF_DEPS
 )
 
-TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC "-lm -ldl")
+TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC
+  ${TARGET_LAUNCHPAD_COMMON} "-lm -ldl")
 
 CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/packaging/default.debugger.in
   ${CMAKE_SOURCE_DIR}/packaging/default.debugger @ONLY)
index 3daf3df..25baf15 100644 (file)
@@ -1,2 +1,3 @@
 ADD_SUBDIRECTORY(launchpad)
+ADD_SUBDIRECTORY(launchpad-common)
 ADD_SUBDIRECTORY(launchpad-hydra)
diff --git a/src/lib/launchpad-common/CMakeLists.txt b/src/lib/launchpad-common/CMakeLists.txt
new file mode 100644 (file)
index 0000000..35449e3
--- /dev/null
@@ -0,0 +1,35 @@
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ LAUNCHPAD_COMMON_SRCS)
+
+ADD_LIBRARY(${TARGET_LAUNCHPAD_COMMON} SHARED ${LAUNCHPAD_COMMON_SRCS})
+
+SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_COMMON} PROPERTIES
+  SOVERSION ${MAJORVER})
+SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_COMMON} PROPERTIES
+  VERSION ${VERSION})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_COMMON} PUBLIC
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${CMAKE_CURRENT_SOURCE_DIR}/../
+)
+
+APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_COMMON} PUBLIC
+  BUNDLE_DEPS
+  DLOG_DEPS
+  GIO_DEPS
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_COMMON} PUBLIC "-ldl")
+
+INSTALL(TARGETS ${TARGET_LAUNCHPAD_COMMON} DESTINATION ${LIB_INSTALL_DIR}
+  COMPONENT RuntimeLibraries)
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
+  DESTINATION include/launchpad-common
+  FILES_MATCHING
+  PATTERN "*_private.hh" EXCLUDE
+  PATTERN "*.hh"
+)
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/liblaunchpad-common.pc.in
+  ${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/liblaunchpad-common.pc @ONLY)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/liblaunchpad-common.pc
+  DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
diff --git a/src/lib/launchpad-common/client_socket.cc b/src/lib/launchpad-common/client_socket.cc
new file mode 100644 (file)
index 0000000..849f4cf
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * 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 "launchpad-common/client_socket.hh"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "launchpad-common/log_private.hh"
+
+namespace launchpad {
+namespace {
+
+constexpr const int MAX_RETRY_CNT = 2;
+
+}  // namespace
+
+ClientSocket::ClientSocket() {
+  fd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+  if (fd_ < 0) {
+    int error = -errno;
+    _E("socket() is failed. errno(%d)", errno);
+    THROW(error);
+  }
+}
+
+ClientSocket::ClientSocket(int fd) : fd_(fd) {}
+
+ClientSocket::~ClientSocket() {
+  Close();
+}
+
+void ClientSocket::Close() {
+  if (fd_ > -1) {
+    close(fd_);
+    fd_ = -1;
+  }
+}
+
+void ClientSocket::Connect(const std::string& endpoint) {
+  int flag = fcntl(fd_, F_GETFL, 0);
+  if (flag == -1) {
+    int ret = -errno;
+    _E("Failed to fcntl(%d, F_GETFL, 0). errno(%d)", fd_, errno);
+    THROW(ret);
+  }
+
+  fcntl(fd_, F_SETFL, flag | O_NONBLOCK);
+  struct sockaddr_un sockaddr = { 0, };
+  sockaddr.sun_family = AF_UNIX;
+  snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s",
+      endpoint.c_str());
+  struct sockaddr* sockaddr_ptr = reinterpret_cast<struct sockaddr*>(&sockaddr);
+  socklen_t len = static_cast<socklen_t>(sizeof(sockaddr));
+
+  int ret;
+  int retry = 2;
+  do {
+    ret = connect(fd_, sockaddr_ptr, len);
+    if (ret == 0)
+      break;
+
+    retry--;
+    ret = -errno;
+    usleep(100 * 1000);
+  } while (retry > 0);
+
+  fcntl(fd_, F_SETFL, flag);
+  if (ret < 0) {
+    _E("connect() is failed. errno(%d)", -ret);
+    THROW(ret);
+  }
+}
+
+int ClientSocket::Send(const void* buf, unsigned int size) {
+  const unsigned char* buffer = static_cast<const unsigned char*>(buf);
+  size_t len = size;
+  int retry_cnt = MAX_RETRY_CNT;
+  while (len) {
+    ssize_t bytes = send(fd_, buffer, len, MSG_NOSIGNAL | MSG_DONTWAIT);
+    if (bytes < 0) {
+      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
+        if (retry_cnt > 0) {
+          retry_cnt--;
+          _E("send(): fd(%d), errno(%d). sleep and retry ...", fd_, errno);
+          usleep(10 * 1000);
+          continue;
+        }
+      }
+
+      _E("send() is failed. fd(%d), errno(%d)", fd_, errno);
+      return -ECOMM;
+    }
+
+    len -= bytes;
+    buffer += bytes;
+  }
+
+  return 0;
+}
+
+int ClientSocket::Receive(void* buf, unsigned int size) {
+  bool is_blocking;
+  if (fcntl(fd_, F_GETFL, 0) & O_NONBLOCK)
+    is_blocking = false;
+  else
+    is_blocking = true;
+
+  int retry_count = 20;
+  unsigned char* buffer = static_cast<unsigned char*>(buf);
+  size_t len = size;
+  while (len) {
+    ssize_t bytes = recv(fd_, buffer, len, 0);
+    if (bytes == 0) {
+      _W("EOF. fd(%d)", fd_);
+      return -ECOMM;
+    }
+
+    if (bytes < 0) {
+      if (errno == EINTR || errno == EAGAIN) {
+        if (is_blocking && errno == EAGAIN) {
+          _E("Timed out. fd(%d)", fd_);
+          return -EAGAIN;
+        }
+
+        if (retry_count > 0) {
+          usleep(100 * 1000);
+          retry_count--;
+          continue;
+        }
+      }
+
+      _E("recv() is failed. fd(%d), errno(%d)", fd_, errno);
+      return -ECOMM;
+    }
+
+    len -= bytes;
+    buffer += bytes;
+  }
+
+  return 0;
+}
+
+
+int ClientSocket::GetReceiveBufferSize() {
+  int value;
+  socklen_t len = sizeof(int);
+  int ret = getsockopt(fd_, SOL_SOCKET, SO_RCVBUF,
+      reinterpret_cast<void*>(&value), &len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("getsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+
+  return value;
+}
+
+int ClientSocket::GetSendBufferSize() {
+  int value;
+  socklen_t len = sizeof(int);
+  int ret = getsockopt(fd_, SOL_SOCKET, SO_SNDBUF,
+      reinterpret_cast<void*>(&value), &len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("getsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+
+  return value;
+}
+
+int ClientSocket::GetReceiveTimeout() {
+  struct timeval timeout = { 0, };
+  socklen_t len = static_cast<socklen_t>(sizeof(struct timeval));
+  int ret = getsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO,
+      reinterpret_cast<void*>(&timeout), &len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("getsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+
+  int value = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
+  return value;
+}
+
+void ClientSocket::SetReceiveBufferSize(int size) {
+  socklen_t len = sizeof(size);
+  int ret = setsockopt(fd_, SOL_SOCKET, SO_RCVBUF, &size, len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("setsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+}
+
+void ClientSocket::SetSendBufferSize(int size) {
+  socklen_t len = sizeof(size);
+  int ret = setsockopt(fd_, SOL_SOCKET, SO_SNDBUF, &size, len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("setsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+}
+
+void ClientSocket::SetReceiveTimeout(int timeout) {
+  if (timeout == INT_MAX)
+    return;
+
+  if (timeout == -1)
+    timeout = 5000;
+
+  if (timeout < 0) {
+    _E("Invalid parameter");
+    THROW(-EINVAL);
+  }
+
+  struct timeval tv = {
+    .tv_sec = static_cast<time_t>(timeout / 1000),
+    .tv_usec = static_cast<suseconds_t>((timeout % 1000) * 1000)
+  };
+  socklen_t len = static_cast<socklen_t>(sizeof(struct timeval));
+  int ret = setsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO, &tv, len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("setsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+}
+
+bool ClientSocket::IsClosed() const {
+  return fd_ < 0;
+}
+
+int ClientSocket::GetFd() const {
+  return fd_;
+}
+
+int ClientSocket::RemoveFd() {
+  int fd = fd_;
+  fd_ = -1;
+  return fd;
+}
+
+}  // namespace launchpad
diff --git a/src/lib/launchpad-common/client_socket.hh b/src/lib/launchpad-common/client_socket.hh
new file mode 100644 (file)
index 0000000..ebb73a2
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef LIB_LAUNCHPAD_COMMON_CLIENT_SOCKET_HH_
+#define LIB_LAUNCHPAD_COMMON_CLIENT_SOCKET_HH_
+
+#include <string>
+
+#include <exception.hh>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API ClientSocket {
+ public:
+  ClientSocket();
+  explicit ClientSocket(int fd);
+  virtual ~ClientSocket();
+  ClientSocket(const ClientSocket&) = delete;
+  ClientSocket& operator = (const ClientSocket&) = delete;
+
+  void Close();
+  void Connect(const std::string& endpoint);
+  int Send(const void* buf, size_t size);
+  int Receive(void* buf, size_t size);
+  int GetReceiveBufferSize();
+  int GetSendBufferSize();
+  int GetReceiveTimeout();
+  void SetReceiveBufferSize(int size);
+  void SetSendBufferSize(int size);
+  void SetReceiveTimeout(int timeout);
+  bool IsClosed() const;
+  int GetFd() const;
+  int RemoveFd();
+
+ private:
+  int fd_;
+};
+
+}  // namespace launchpad
+
+#endif  // LIB_LAUNCHPAD_COMMON_CLIENT_SOCKET_HH_
diff --git a/src/lib/launchpad-common/exception.cc b/src/lib/launchpad-common/exception.cc
new file mode 100644 (file)
index 0000000..c909499
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * 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 "launchpad-common/exception.hh"
+
+namespace launchpad {
+
+Exception::Exception(int error_code, std::string file, int line)
+    : error_code_(error_code) {
+  message_ = file.substr(file.find_last_of("/") + 1) + ":" +
+      std::to_string(line) + " code:" + std::to_string(error_code_);
+}
+
+Exception::~Exception() {}
+
+const char* Exception::what(void) const noexcept {
+  return message_.c_str();
+}
+
+int Exception::GetErrorCode() const {
+  return error_code_;
+}
+
+}  // namespace launchpad
diff --git a/src/lib/launchpad-common/exception.hh b/src/lib/launchpad-common/exception.hh
new file mode 100644 (file)
index 0000000..9c2a0a6
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * 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 LIB_LAUNCHPAD_COMMON_EXCEPTION_HH_
+#define LIB_LAUNCHPAD_COMMON_EXCEPTION_HH_
+
+#include <exception>
+#include <string>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+#define THROW(error) throw launchpad::Exception(error, __FUNCTION__, __LINE__)
+
+namespace launchpad {
+
+class EXPORT_API Exception : public std::exception {
+ public:
+  explicit Exception(int error_code, std::string file, int line);
+  virtual ~Exception();
+
+  virtual const char* what(void) const noexcept;
+  int GetErrorCode() const;
+
+ private:
+  int error_code_;
+  std::string message_;
+};
+
+}  // namespace launchpad
+
+#endif  // LIB_LAUNCHPAD_COMMON_EXCEPTION_HH_
diff --git a/src/lib/launchpad-common/io_channel.cc b/src/lib/launchpad-common/io_channel.cc
new file mode 100644 (file)
index 0000000..10ddbb9
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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 "launchpad-common/io_channel.hh"
+
+#include <errno.h>
+
+#include <memory>
+
+#include "launchpad-common/log_private.hh"
+
+namespace launchpad {
+
+IOChannel::IOChannel(int fd, int condition, IOChannel::IEvent* listener)
+    : fd_(fd), listener_(listener) {
+  auto channel = g_io_channel_unix_new(fd_);
+  if (channel == nullptr) {
+    _E("g_io_channel_unix_new() is failed");
+    THROW(-ENOMEM);
+  }
+  auto channel_auto =
+      std::unique_ptr<GIOChannel, decltype(g_io_channel_unref)*>(
+          channel, g_io_channel_unref);
+
+  source_id_ = g_io_add_watch(channel, static_cast<GIOCondition>(condition),
+      IOEventCb, this);
+  if (source_id_ == 0) {
+    _E("g_io_add_watch() is failed");
+    THROW(-ENOMEM);
+  }
+
+  channel_ = channel_auto.release();
+}
+
+IOChannel::~IOChannel() {
+  if (source_id_ != 0)
+    g_source_remove(source_id_);
+
+  if (channel_ != nullptr)
+    g_io_channel_unref(channel_);
+}
+
+void IOChannel::SetCloseOnDestroy(bool do_close) {
+  g_io_channel_set_close_on_unref(channel_, do_close);
+}
+
+gboolean IOChannel::IOEventCb(GIOChannel* channel, GIOCondition condition,
+    gpointer user_data) {
+  auto* io_channel = static_cast<IOChannel*>(user_data);
+  auto* listener = io_channel->listener_;
+  if (listener != nullptr)
+    listener->OnIOEventReceived(io_channel->fd_, static_cast<int>(condition));
+
+  return G_SOURCE_CONTINUE;
+}
+
+
+}  // namespace launchpad
diff --git a/src/lib/launchpad-common/io_channel.hh b/src/lib/launchpad-common/io_channel.hh
new file mode 100644 (file)
index 0000000..12056a7
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#ifndef LIB_LAUNCHPAD_COMMON_IO_CHANNEL_HH_
+#define LIB_LAUNCHPAD_COMMON_IO_CHANNEL_HH_
+
+#include <gio/gio.h>
+
+#include <exception.hh>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API IOChannel {
+ public:
+  enum IOCondition {
+    IO_IN = G_IO_IN,
+    IO_OUT = G_IO_OUT,
+    IO_PRI = G_IO_PRI,
+    IO_ERR = G_IO_ERR,
+    IO_HUP = G_IO_HUP,
+    IO_NVAL = G_IO_NVAL,
+  };
+
+  class IEvent {
+   public:
+    virtual ~IEvent() = default;
+    virtual void OnIOEventReceived(int fd, int condition);
+  };
+
+  IOChannel(int fd, int condtion, IEvent* listener);
+  virtual ~IOChannel();
+
+  IOChannel(const IOChannel&) = delete;
+  IOChannel& operator = (const IOChannel&) = delete;
+
+  void SetCloseOnDestroy(bool do_close);
+
+ private:
+  static gboolean IOEventCb(GIOChannel* channel, GIOCondition condition,
+      gpointer user_data);
+
+ private:
+  int fd_;
+  IEvent* listener_ = nullptr;
+  GIOChannel* channel_ = nullptr;
+  guint source_id_ = 0;
+};
+
+}  // namespace launchpad
+
+#endif  // LIB_LAUNCHPAD_COMMON_IO_CHANNEL_HH_
diff --git a/src/lib/launchpad-common/log_private.hh b/src/lib/launchpad-common/log_private.hh
new file mode 100644 (file)
index 0000000..47d5a15
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef LIB_LAUNCHPAD_COMMON_LOG_PRIVATE_HH_
+#define LIB_LAUNCHPAD_COMMON_LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "LAUNCHPAD_COMMON"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif  // LIB_LAUNCHPAD_COMMON_LOG_PRIVATE_HH_
diff --git a/src/lib/launchpad-common/pkgconfig/liblaunchpad-common.pc.in b/src/lib/launchpad-common/pkgconfig/liblaunchpad-common.pc.in
new file mode 100644 (file)
index 0000000..6b5cff3
--- /dev/null
@@ -0,0 +1,13 @@
+# Package Information for pkg-config
+
+prefix=/usr
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@
+
+Name: liblaunchpad-common
+Description: launchpad common library
+Version: @VERSION@
+Requires: bundle dlog
+Libs: -L${libdir} -llaunchpad-common
+Cflags: -I${includedir} -I${includedir}/launchpad-common
diff --git a/src/lib/launchpad-common/server_socket.cc b/src/lib/launchpad-common/server_socket.cc
new file mode 100644 (file)
index 0000000..772c196
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * 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 "launchpad-common/server_socket.hh"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "launchpad-common/exception.hh"
+#include "launchpad-common/log_private.hh"
+
+namespace launchpad {
+
+ServerSocket::ServerSocket() {
+  fd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+  if (fd_ < 0) {
+    fd_ = -errno;
+    _E("socket() is failed. errno(%d)", errno);
+    THROW(fd_);
+  }
+}
+
+ServerSocket::ServerSocket(int fd) : fd_(fd) {}
+
+ServerSocket::~ServerSocket() {
+  Close();
+}
+
+std::unique_ptr<ClientSocket> ServerSocket::Accept() {
+  struct sockaddr_un addr = { 0, };
+  socklen_t len = static_cast<socklen_t>(sizeof(struct sockaddr_un));
+  auto* addr_ptr = reinterpret_cast<struct sockaddr*>(&addr);
+  int client_fd = accept(GetFd(), addr_ptr, &len);
+  if (client_fd == -1) {
+    _E("accept() is failed. errno(%d)", errno);
+    return nullptr;
+  }
+
+  return std::unique_ptr<ClientSocket>(new ClientSocket(client_fd));
+}
+
+void ServerSocket::Bind(const std::string& bindpoint) {
+  struct sockaddr_un sockaddr = { 0, };
+  sockaddr.sun_family = AF_UNIX;
+  snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s",
+      bindpoint.c_str());
+  struct sockaddr* sockaddr_ptr = reinterpret_cast<struct sockaddr*>(&sockaddr);
+  socklen_t len = static_cast<socklen_t>(sizeof(sockaddr));
+
+  unlink(bindpoint.c_str());
+  int ret = bind(GetFd(), sockaddr_ptr, len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("bind() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+}
+
+void ServerSocket::Close() {
+  if (fd_ > -1) {
+    close(fd_);
+    fd_ = -1;
+  }
+}
+
+void ServerSocket::Listen(int backlog) {
+  int ret = listen(fd_, backlog);
+  if (ret < 0) {
+    ret = -errno;
+    _E("listen() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+}
+
+int ServerSocket::GetReceiveBufferSize() {
+  int value;
+  socklen_t len = sizeof(int);
+  int ret = getsockopt(fd_, SOL_SOCKET, SO_RCVBUF,
+      reinterpret_cast<void*>(&value), &len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("getsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+
+  return value;
+}
+
+int ServerSocket::GetSendBufferSize() {
+  int value;
+  socklen_t len = sizeof(int);
+  int ret = getsockopt(fd_, SOL_SOCKET, SO_SNDBUF,
+      reinterpret_cast<void*>(&value), &len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("getsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+
+  return value;
+}
+
+void ServerSocket::SetReceiveBufferSize(int size) {
+  socklen_t len = sizeof(size);
+  int ret = setsockopt(fd_, SOL_SOCKET, SO_RCVBUF, &size, len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("setsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+}
+
+void ServerSocket::SetSendBufferSize(int size) {
+  socklen_t len = sizeof(size);
+  int ret = setsockopt(fd_, SOL_SOCKET, SO_SNDBUF, &size, len);
+  if (ret < 0) {
+    ret = -errno;
+    _E("setsockopt() is failed. errno(%d)", errno);
+    THROW(ret);
+  }
+}
+
+bool ServerSocket::IsClosed() const {
+  return fd_ < 0;
+}
+
+int ServerSocket::GetFd() const {
+  return fd_;
+}
+
+int ServerSocket::RemoveFd() {
+  int fd = fd_;
+  fd_ = -1;
+  return fd;
+}
+
+}  // namespace launchpad
diff --git a/src/lib/launchpad-common/server_socket.hh b/src/lib/launchpad-common/server_socket.hh
new file mode 100644 (file)
index 0000000..603d6e7
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef LIB_LAUNCHPAD_COMMON_SERVER_SOCKET_HH_
+#define LIB_LAUNCHPAD_COMMON_SERVER_SOCKET_HH_
+
+#include <memory>
+#include <string>
+
+#include <client_socket.hh>
+#include <exception.hh>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API ServerSocket {
+ public:
+  ServerSocket();
+  explicit ServerSocket(int fd);
+  virtual ~ServerSocket();
+  ServerSocket(const ServerSocket&) = delete;
+  ServerSocket& operator = (const ServerSocket&) = delete;
+
+  std::unique_ptr<ClientSocket> Accept();
+  void Bind(const std::string& bindpoint);
+  void Close();
+  void Listen(int backlog);
+  int GetReceiveBufferSize();
+  int GetSendBufferSize();
+  void SetReceiveBufferSize(int size);
+  void SetSendBufferSize(int size);
+  bool IsClosed() const;
+  int GetFd() const;
+  int RemoveFd();
+
+ private:
+  int fd_;
+};
+
+}  // namespace launchpad
+
+#endif  // LIB_LAUNCHPAD_COMMON_SERVER_SOCKET_HH_