Refactor aul sock 27/277027/6
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 29 Jun 2022 07:41:17 +0000 (16:41 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 30 Jun 2022 06:38:20 +0000 (15:38 +0900)
The aul sock is implemented using C++.

Change-Id: I34573294f754e2469d19bd2867f89a6d7f88bc51
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
aul/common/exception.hh
aul/socket/client_socket.cc [new file with mode: 0644]
aul/socket/client_socket.hh [new file with mode: 0644]
aul/socket/server_socket.cc [new file with mode: 0644]
aul/socket/server_socket.hh [new file with mode: 0644]
aul/socket/socket.cc
aul/socket/socket.hh
src/aul_sock.c [deleted file]
src/aul_sock.cc [new file with mode: 0644]
test/unit_tests/main.cc

index 4d7fa1c..a4022e0 100644 (file)
@@ -33,7 +33,6 @@ class Exception : public std::exception {
     error_code_ = error_code;
     message_ = file.substr(file.find_last_of("/") + 1) + ":"
         + std::to_string(line) + " code:" + std::to_string(error_code_);
-    _E("%s", message_.c_str());
   }
 
   virtual ~Exception() {}
@@ -42,7 +41,7 @@ class Exception : public std::exception {
     return message_.c_str();
   }
 
-  int GetErrorCode() {
+  int GetErrorCode() const {
     return error_code_;
   }
 
diff --git a/aul/socket/client_socket.cc b/aul/socket/client_socket.cc
new file mode 100644 (file)
index 0000000..3f3e793
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2022 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 "aul/socket/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>
+
+namespace aul {
+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);
+  fcntl(GetFd(), 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 = sizeof(sockaddr);
+
+  int ret;
+  int retry = 2;
+  do {
+    ret = connect(fd_, sockaddr_ptr, len);
+    if (ret == 0)
+      break;
+
+    retry--;
+    usleep(100 * 1000);
+  } while (retry > 0);
+
+  fcntl(fd_, F_SETFL, flag);
+  if (ret < 0) {
+    ret = -errno;
+    _E("connect() is failed. errno(%d)", errno);
+    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 = 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 = 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() {
+  return fd_ < 0;
+}
+
+int ClientSocket::GetFd() const {
+  return fd_;
+}
+
+int ClientSocket::RemoveFd() {
+  int fd = fd_;
+  fd_ = -1;
+  return fd;
+}
+
+}  // namespace aul
diff --git a/aul/socket/client_socket.hh b/aul/socket/client_socket.hh
new file mode 100644 (file)
index 0000000..70c987c
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022 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 AUL_SOCKET_CLIENT_SOCKET_HH_
+#define AUL_SOCKET_CLIENT_SOCKET_HH_
+
+#include <memory>
+#include <string>
+
+#include "aul/common/exception.hh"
+
+namespace aul {
+
+class ClientSocket {
+ public:
+  ClientSocket();
+  explicit ClientSocket(int fd);
+  virtual ~ClientSocket();
+
+  void Close();
+  void Connect(const std::string& endpoint);
+  int Send(const void* buf, unsigned int size);
+  int Receive(void* buf, unsigned int size);
+  int GetReceiveBufferSize();
+  int GetSendBufferSize();
+  int GetReceiveTimeout();
+  void SetReceiveBufferSize(int size);
+  void SetSendBufferSize(int size);
+  void SetReceiveTimeout(int timeout);
+  bool IsClosed();
+  int GetFd() const;
+  int RemoveFd();
+
+ private:
+  int fd_;
+};
+
+}  // namespace aul
+
+#endif  // AUL_SOCKET_CLIENT_SOCKET_HH_
diff --git a/aul/socket/server_socket.cc b/aul/socket/server_socket.cc
new file mode 100644 (file)
index 0000000..12da427
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2022 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 "aul/socket/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 "aul/common/exception.hh"
+#include "aul/common/log_private.hh"
+
+namespace aul {
+
+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();
+}
+
+ClientSocket* ServerSocket::Accept() {
+  struct sockaddr_un addr = { 0, };
+  socklen_t len = 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 new (std::nothrow) 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 = 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() {
+  return fd_ < 0;
+}
+
+int ServerSocket::GetFd() const {
+  return fd_;
+}
+
+int ServerSocket::RemoveFd() {
+  int fd = fd_;
+  fd_ = -1;
+  return fd;
+}
+
+}  // namespace aul
diff --git a/aul/socket/server_socket.hh b/aul/socket/server_socket.hh
new file mode 100644 (file)
index 0000000..dbd4105
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022 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 AUL_SOCKET_SERVER_SOCKET_HH_
+#define AUL_SOCKET_SERVER_SOCKET_HH_
+
+#include <memory>
+#include <string>
+
+#include "aul/common/exception.hh"
+#include "aul/socket/client_socket.hh"
+
+namespace aul {
+
+class ServerSocket {
+ public:
+  ServerSocket();
+  explicit ServerSocket(int fd);
+  virtual ~ServerSocket();
+
+  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();
+  int GetFd() const;
+  int RemoveFd();
+
+ private:
+  int fd_;
+};
+
+}  // namespace aul
+
+#endif  // AUL_SOCKET_SERVER_SOCKET_HH_
index 46487f0..46deda0 100644 (file)
@@ -151,14 +151,20 @@ int Socket::Connect() {
   return -1;
 }
 
-int Socket::GetFd() {
+int Socket::GetFd() const {
   return fd_;
 }
 
-std::string Socket::GetPath() {
+const std::string& Socket::GetPath() const {
   return path_;
 }
 
+int Socket::RemoveFd() {
+  int fd = fd_;
+  fd_ = -1;
+  return fd;
+}
+
 void Socket::SetOption() {
   int size = MAX_AUL_BUFF_SIZE;
   int ret = setsockopt(fd_, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
index 6cb084b..928ad9f 100644 (file)
@@ -40,9 +40,10 @@ class Socket {
   int Listen();
   int Connect();
 
-  int GetFd();
+  int GetFd() const;
   void SetTimeout(int timeout_msec);
-  std::string GetPath();
+  const std::string& GetPath() const;
+  int RemoveFd();
 
  private:
   void SetOption();
diff --git a/src/aul_sock.c b/src/aul_sock.c
deleted file mode 100644 (file)
index 5ad51b7..0000000
+++ /dev/null
@@ -1,1000 +0,0 @@
-/*
- * Copyright (c) 2000 - 2018 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.
- */
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/xattr.h>
-#include <tzplatform_config.h>
-#include <glib.h>
-#include <vconf.h>
-
-#include "aul_api.h"
-#include "aul_sock.h"
-#include "aul_util.h"
-
-#define MAX_NR_OF_DESCRIPTORS 2
-#define MAX_PAYLOAD_SIZE       (1024 * 1024 * 1)
-#define PATH_AMD_SOCK "/run/aul/daemons/.amd-sock"
-
-#define REGULAR_UID_MIN 5000
-
-typedef struct app_pkt_header_s {
-       int cmd;
-       int len;
-       int opt;
-} app_pkt_header_t;
-
-static int socket_timeout_initialized;
-static int socket_link_created;
-static char socket_link_path[108];
-
-static struct timeval tv = { 5, 200 * 1000 }; /* 5.2 */
-
-static int __connect_client_sock(int sockfd, const struct sockaddr *saptr,
-               socklen_t salen, int nsec);
-
-static int __recv_raw(int fd, unsigned char *data, size_t data_size)
-{
-       ssize_t recv_size = 0;
-       ssize_t r;
-       size_t size = data_size;
-       bool is_blocking;
-       int retry_count = 20;
-
-       if (fcntl(fd, F_GETFL, 0) & O_NONBLOCK)
-               is_blocking = false;
-       else
-               is_blocking = true;
-
-       while (size > 0) {
-               r = recv(fd, data, size, 0);
-               if (r == 0) {
-                       _W("Socket was disconnected. fd(%d)", fd);
-                       return -ECOMM;
-               } else if (r < 0) {
-                       if (errno == EINTR || errno == EAGAIN) {
-                               if (is_blocking && errno == EAGAIN) {
-                                       _E("recv timeout. fd(%d)", fd);
-                                       return -EAGAIN;
-                               }
-
-                               if (retry_count > 0) {
-                                       usleep(100 * 1000);
-                                       retry_count--;
-                                       continue;
-                               }
-                       }
-
-                       _E("recv error. fd(%d), errno(%d)",
-                                       fd, errno);
-                       return -ECOMM;
-               }
-
-               size -= r;
-               data += r;
-               recv_size += r;
-       }
-
-       if (recv_size != data_size) {
-               _E("Failed to receive messages. fd(%d)", fd);
-               return -ECOMM;
-       }
-
-       return 0;
-}
-
-static int __recv_pkt(int fd, app_pkt_t **out_pkt)
-{
-       app_pkt_header_t header = { 0, };
-       app_pkt_t *pkt;
-       int r;
-
-       *out_pkt = NULL;
-       r = __recv_raw(fd, (unsigned char *)&header, sizeof(header));
-       if (r < 0) {
-               _E("Failed to receive packet header");
-               return r;
-       }
-
-       if (header.len < 0 || header.len > MAX_PAYLOAD_SIZE) {
-               _E("Invalid protocol. length(%d)", header.len);
-               return -ECOMM;
-       }
-
-       pkt = calloc(1, sizeof(app_pkt_t) + header.len);
-       if (!pkt) {
-               _E("Out of memory");
-               return -ECOMM;
-       }
-       pkt->cmd = header.cmd;
-       pkt->len = header.len;
-       pkt->opt = header.opt;
-
-       r = __recv_raw(fd, (unsigned char *)pkt->data, pkt->len);
-       if (r < 0) {
-               free(pkt);
-               return r;
-       }
-
-       *out_pkt = pkt;
-
-       return 0;
-}
-
-static void __set_timeval(double sec)
-{
-       char buf[12];
-       gchar *ptr = NULL;
-
-       snprintf(buf, sizeof(buf), "%.3f", sec);
-       tv.tv_sec = g_ascii_strtoull(buf, &ptr, 10);
-       tv.tv_usec = g_ascii_strtoull(ptr + 1, &ptr, 10) * 1000;
-       _D("tv_sec: %ld, tv_usec: %ld", (long)tv.tv_sec, (long)tv.tv_usec);
-}
-
-static void __socket_timeout_vconf_cb(keynode_t *key, void *data)
-{
-       const char *name;
-       double sec;
-
-       name = vconf_keynode_get_name(key);
-       if (name && strcmp(name, VCONFKEY_AUL_SOCKET_TIMEOUT) == 0) {
-               sec = vconf_keynode_get_dbl(key);
-               __set_timeval(sec);
-       }
-}
-
-static void __init_socket_timeout(void)
-{
-       int r;
-       double sec = 5.2f;
-
-       r = access("/run/aul/.socket_timeout", F_OK);
-       if (r < 0) {
-               socket_timeout_initialized = 1;
-               return;
-       }
-
-       r = vconf_get_dbl(VCONFKEY_AUL_SOCKET_TIMEOUT, &sec);
-       if (r < 0)
-               _D("Failed to get vconf: %s", VCONFKEY_AUL_SOCKET_TIMEOUT);
-
-       r = vconf_notify_key_changed(VCONFKEY_AUL_SOCKET_TIMEOUT,
-                       __socket_timeout_vconf_cb, NULL);
-       if (r < 0) {
-               _E("Failed to register callback for %s",
-                               VCONFKEY_AUL_SOCKET_TIMEOUT);
-               return;
-       }
-
-       __set_timeval(sec);
-       socket_timeout_initialized = 1;
-}
-
-API struct timeval aul_sock_get_rcv_timeval(void)
-{
-       return tv;
-}
-
-API int aul_sock_set_sock_option(int fd, int cli)
-{
-       int size;
-       int r;
-
-       size = AUL_SOCK_MAXBUFF;
-       r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
-       if (r < 0)
-               return r;
-
-       r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
-       if (r < 0)
-               return r;
-
-       if (cli) {
-               if (TIZEN_FEATURE_SOCKET_TIMEOUT && !socket_timeout_initialized)
-                       __init_socket_timeout();
-               r = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
-               if (r < 0)
-                       return r;
-       }
-
-       return 0;
-}
-
-static int __create_socket_dir(int pid, uid_t uid)
-{
-       char path[108];
-
-       if (uid < REGULAR_UID_MIN)
-               snprintf(path, sizeof(path), "/run/aul/daemons/%d", uid);
-       else
-               snprintf(path, sizeof(path), "/run/aul/apps/%d/%d", uid, pid);
-
-       if (mkdir(path, 0700) != 0) {
-               if (errno == EEXIST) {
-                       if (access(path, R_OK) != 0) {
-                               _E("Failed to acess %s directory", path);
-                               return -1;
-                       }
-               } else {
-                       _E("Failed to create %s directory", path);
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-static void __create_socket_path(char *path_buf, int size, int pid, uid_t uid)
-{
-       if (uid < REGULAR_UID_MIN) {
-               snprintf(path_buf, size,
-                       "/run/aul/daemons/%d/.app-sock-%d", uid, pid);
-       } else {
-               snprintf(path_buf, size,
-                       "/run/aul/apps/%d/%d/.app-sock", uid, pid);
-       }
-}
-
-static void __create_socket_link(const char *socket_path, int pid, uid_t uid)
-{
-       char path[108];
-
-       if (__create_socket_dir(pid, uid) < 0)
-               return;
-
-       __create_socket_path(path, sizeof(path), pid, uid);
-       if (link(socket_path, path) < 0) {
-               if (errno == EEXIST)
-                       _D("path(%s) - already exists", path);
-               else
-                       _E("path(%s) - unknown create error", path);
-       }
-
-       snprintf(socket_link_path, sizeof(socket_link_path), "%s", path);
-       socket_link_created = 1;
-}
-
-API int aul_sock_create_server(int pid, uid_t uid)
-{
-       struct sockaddr_un saddr;
-       int fd;
-       int env_pid = -1;
-       char *env_str;
-
-       fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
-       /*  support above version 2.6.27*/
-       if (fd < 0) {
-               if (errno == EINVAL) {
-                       fd = socket(AF_UNIX, SOCK_STREAM, 0);
-                       if (fd < 0) {
-                               _E("second chance - socket create error");
-                               return -1;
-                       }
-               } else {
-                       _E("socket error");
-                       return -1;
-               }
-       }
-
-       memset(&saddr, 0, sizeof(saddr));
-       saddr.sun_family = AF_UNIX;
-
-       if (__create_socket_dir(pid, uid) < 0) {
-               close(fd);
-               return -1;
-       }
-
-       __create_socket_path(saddr.sun_path, sizeof(saddr.sun_path), pid, uid);
-       unlink(saddr.sun_path);
-
-       /* labeling to socket for SMACK */
-       if (getuid() == 0) {    /* this is meaningful if current user is ROOT */
-               if (fsetxattr(fd, "security.SMACK64IPOUT", "@", 1, 0) < 0) {
-                       /* in case of unsupported filesystem on 'socket' */
-                       /* or permission error by using 'emulator', bypass*/
-                       if ((errno != EOPNOTSUPP) && (errno != EPERM)) {
-                               _E("labeling to socket(IPOUT) error");
-                               close(fd);
-                               return -1;
-                       }
-               }
-               if (fsetxattr(fd, "security.SMACK64IPIN", "*", 1, 0) < 0) {
-                       /* in case of unsupported filesystem on 'socket' */
-                       /* or permission error by using 'emulator', bypass*/
-                       if ((errno != EOPNOTSUPP) && (errno != EPERM)) {
-                               _E("labeling to socket(IPIN) error");
-                               close(fd);
-                               return -1;
-                       }
-               }
-       }
-
-       if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
-               _E("bind error");
-               close(fd);
-               return -1;
-       }
-
-       aul_sock_set_sock_option(fd, 0);
-
-       if (listen(fd, 128) == -1) {
-               _E("listen error");
-               close(fd);
-               return -1;
-       }
-
-       /* Create socket link */
-       if (pid > 0) {
-               env_str = getenv("AUL_PID");
-               if (env_str && isdigit(env_str[0]))
-                       env_pid = atoi(env_str);
-
-               if (env_pid > 1 && pid != env_pid)
-                       __create_socket_link(saddr.sun_path, env_pid, uid);
-       }
-
-       return fd;
-}
-
-static int __create_client_sock(int pid, uid_t uid)
-{
-       int fd = -1;
-       struct sockaddr_un saddr = { 0, };
-       int retry = 2;
-       int ret = -1;
-
-       fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
-       /*  support above version 2.6.27*/
-       if (fd < 0) {
-               if (errno == EINVAL) {
-                       fd = socket(AF_UNIX, SOCK_STREAM, 0);
-                       if (fd < 0) {
-                               _E("second chance - socket create error");
-                               return -1;
-                       }
-               } else {
-                       _E("socket error");
-                       return -1;
-               }
-       }
-
-       saddr.sun_family = AF_UNIX;
-       if (pid == AUL_UTIL_PID) {
-               snprintf(saddr.sun_path, sizeof(saddr.sun_path),
-                               "%s", PATH_AMD_SOCK);
-       } else {
-               __create_socket_path(saddr.sun_path, sizeof(saddr.sun_path), pid, uid);
-       }
-
-retry_con:
-       ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr),
-                       100 * 1000);
-       if (ret < -1) {
-               _E("maybe peer not launched or peer(%d:%u) dead. fd(%d)",
-                               pid, uid, fd);
-               if (retry > 0) {
-                       usleep(100 * 1000);
-                       retry--;
-                       goto retry_con;
-               }
-       }
-
-       if (ret < 0) {
-               _E("Failed to connect the socket. fd(%d), errno(%d)",
-                               fd, errno);
-               close(fd);
-               return -1;
-       }
-
-       aul_sock_set_sock_option(fd, 1);
-
-       return fd;
-}
-
-static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen,
-                  int nsec)
-{
-       int flags;
-       int ret;
-       int error = 0;
-       socklen_t len;
-       fd_set readfds;
-       fd_set writefds;
-       struct timeval timeout;
-
-       flags = fcntl(fd, F_GETFL, 0);
-       fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-
-       ret = connect(fd, (struct sockaddr *)saptr, salen);
-       if (ret < 0) {
-               if (errno != EAGAIN && errno != EINPROGRESS) {
-                       (void)fcntl(fd, F_SETFL, flags);
-                       return -2;
-               }
-       }
-
-       /* Do whatever we want while the connect is taking place. */
-       if (ret == 0)
-               goto done;      /* connect completed immediately */
-
-       FD_ZERO(&readfds);
-       FD_SET(fd, &readfds);
-       writefds = readfds;
-       timeout.tv_sec = 0;
-       timeout.tv_usec = nsec;
-
-       ret = select(fd + 1, &readfds, &writefds, NULL, nsec ? &timeout : NULL);
-       if (ret == 0) {
-               errno = ETIMEDOUT;
-               return -1;
-       }
-
-       if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) {
-               len = sizeof(error);
-               if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
-                       return -1;      /* Solaris pending error */
-       }
-
-       return -1;      /* select error: sockfd not set*/
-
-done:
-       ret = fcntl(fd, F_SETFL, flags);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static int __send_raw_async_with_fd(int fd, int cmd, unsigned char *kb_data, int datalen, int opt)
-{
-       int len;
-       int sent = 0;
-       app_pkt_t *pkt = NULL;
-
-       pkt = (app_pkt_t *)calloc(1, sizeof(app_pkt_t) + datalen);
-       if (NULL == pkt) {
-               _E("Malloc Failed!");
-               return -ENOMEM;
-       }
-
-       pkt->cmd = cmd;
-       pkt->len = datalen;
-       pkt->opt = opt;
-
-       if (kb_data)
-               memcpy(pkt->data, kb_data, pkt->len);
-
-       while (sent != AUL_PKT_HEADER_SIZE + pkt->len) {
-               len = send(fd, (char *)pkt + sent,
-                               AUL_PKT_HEADER_SIZE + pkt->len - sent,
-                               MSG_NOSIGNAL);
-               if (len <= 0) {
-                       _E("send error fd:%d (errno %d)", fd, errno);
-                       free(pkt);
-                       return -ECOMM;
-               }
-               sent += len;
-       }
-
-       free(pkt);
-
-       return 0;
-}
-
-API int aul_sock_send_raw_with_fd(int fd, int cmd, unsigned char *kb_data, int datalen, int opt)
-{
-       int len;
-       int res;
-
-       _D("fd(%d): cmd(%d)", fd, cmd);
-
-       res = __send_raw_async_with_fd(fd, cmd, kb_data, datalen, opt);
-       if (res < 0 || opt & AUL_SOCK_NOREPLY) {
-               if (!(opt & AUL_SOCK_ASYNC))
-                       close(fd);
-               return res;
-       }
-
-       if (opt & AUL_SOCK_ASYNC)
-               return fd;
-
-       len = __recv_raw(fd, (unsigned char *)&res, sizeof(int));
-       if (len < 0)
-               res = len;
-
-       close(fd);
-
-       return res;
-}
-
-API int aul_sock_send_bundle_with_fd(int fd, int cmd, bundle *kb, int opt)
-{
-       bundle_raw *kb_data = NULL;
-       int datalen;
-       int res;
-
-       if (!kb)
-               return -EINVAL;
-
-       res = bundle_encode(kb, &kb_data, &datalen);
-       if (res != BUNDLE_ERROR_NONE)
-               return -EINVAL;
-
-       res = aul_sock_send_raw_with_fd(fd, cmd, kb_data, datalen, opt | AUL_SOCK_BUNDLE);
-
-       if (kb_data)
-               free(kb_data);
-
-       return res;
-}
-
-/*
- * @brief      Send data (in raw) to the process with 'pid' via socket
- */
-API int aul_sock_send_raw(int pid, uid_t uid, int cmd,
-               unsigned char *kb_data, int datalen, int opt)
-{
-       int fd;
-       int r;
-
-       _D("pid(%d): cmd(%d)", pid, cmd);
-
-       fd = __create_client_sock(pid, uid);
-       if (fd < 0)
-               return -ECOMM;
-
-       r = aul_sock_send_raw_with_fd(fd, cmd, kb_data, datalen, opt);
-       if (r < 0) {
-               if (opt & AUL_SOCK_ASYNC)
-                       close(fd);
-       }
-
-       return r;
-}
-
-API int aul_sock_send_bundle(int pid, uid_t uid, int cmd, bundle *kb, int opt)
-{
-       bundle_raw *kb_data = NULL;
-       int datalen;
-       int res;
-
-       if (!kb)
-               return -EINVAL;
-
-       res = bundle_encode(kb, &kb_data, &datalen);
-       if (res != BUNDLE_ERROR_NONE)
-               return -EINVAL;
-
-       res = aul_sock_send_raw(pid, uid, cmd, kb_data, datalen, opt | AUL_SOCK_BUNDLE);
-
-       if (kb_data)
-               free(kb_data);
-
-       return res;
-}
-
-API app_pkt_t *aul_sock_recv_pkt(int fd, int *clifd, struct ucred *cr)
-{
-       struct sockaddr_un aul_addr = { 0, };
-       int sun_size = sizeof(struct sockaddr_un);
-       int cl = sizeof(struct ucred);
-       app_pkt_t *pkt = NULL;
-       int client_fd;
-       int ret;
-
-       client_fd = accept(fd, (struct sockaddr *)&aul_addr,
-                       (socklen_t *)&sun_size);
-       if (client_fd == -1) {
-               if (errno != EINTR)
-                       _E("accept error");
-               return NULL;
-       }
-
-       ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED,
-                       cr, (socklen_t *)&cl);
-       if (ret < 0) {
-               _E("peer information error");
-               close(client_fd);
-               return NULL;
-       }
-
-       aul_sock_set_sock_option(client_fd, 1);
-
-       ret = __recv_pkt(client_fd, &pkt);
-       if (ret < 0) {
-               close(client_fd);
-               return NULL;
-       }
-
-       *clifd = client_fd;
-
-       return pkt;
-}
-
-API int aul_sock_recv_reply_pkt(int fd, app_pkt_t **ret_pkt)
-{
-       return aul_sock_recv_reply_pkt_v2(fd, ret_pkt, true);
-}
-
-static int __get_descriptors(struct cmsghdr *cmsg, struct msghdr *msg, int *fds, int maxdesc)
-{
-       int retnr = 0;
-       int nrdesc;
-       int payload;
-       int *recvdesc;
-       int i;
-
-       if (cmsg == NULL || msg == NULL)
-               return 0;
-       if (cmsg->cmsg_type != SCM_RIGHTS)
-               return 0;
-
-       if (msg->msg_controllen > 0) {
-               payload = cmsg->cmsg_len - sizeof(*cmsg);
-               recvdesc = (int *)CMSG_DATA(cmsg);
-
-               nrdesc = payload / sizeof(int);
-               retnr = nrdesc < maxdesc ? nrdesc : maxdesc;
-               for (i = 0; i < nrdesc; ++i) {
-                       if (maxdesc-- > 0)
-                               *fds++ = *recvdesc++;
-                       else
-                               close(*recvdesc++);
-               }
-       }
-
-       return retnr;
-}
-
-static int __recv_message(int sock, struct iovec *vec, int vec_max_size, int *vec_size,
-               int *fds, int *nr_fds)
-{
-       char buff[CMSG_SPACE(sizeof(int) * MAX_NR_OF_DESCRIPTORS) + CMSG_SPACE(50)] = {0};
-       struct msghdr msg = {0};
-       struct cmsghdr *cmsg = NULL;
-       bool is_blocking;
-       int ret;
-
-       if (vec == NULL || vec_max_size < 1 || vec_size == NULL)
-               return -EINVAL;
-
-       msg.msg_iov = vec;
-       msg.msg_iovlen = vec_max_size;
-       msg.msg_control = buff;
-       msg.msg_controllen = sizeof(buff);
-
-       if (fcntl(sock, F_GETFL, 0) & O_NONBLOCK)
-               is_blocking = false;
-       else
-               is_blocking = true;
-
-retry:
-       ret = recvmsg(sock, &msg, 0);
-       if (ret == 0) {
-               _W("Socket was disconnected. fd(%d)", sock);
-               return -ECOMM;
-       } else if (ret < 0) {
-               if (errno == EINTR || errno == EAGAIN) {
-                       if (is_blocking && errno == EAGAIN) {
-                               _E("recvmsg timeout. fd(%d)", sock);
-                               return -EAGAIN;
-                       }
-
-                       goto retry;
-               }
-
-               ret = -errno;
-               _E("recvmsg error. fd(%d), errno(%d)", sock, errno);
-               return ret;
-       }
-
-       *vec_size = msg.msg_iovlen;
-
-       /* get the ANCILLARY data */
-       cmsg = CMSG_FIRSTHDR(&msg);
-       if (cmsg == NULL) {
-               if (nr_fds != NULL)
-                       *nr_fds = 0;
-       } else {
-               int iter = 0;
-               int fdnum = 0;
-
-               for (; cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg), iter++) {
-                       switch (cmsg->cmsg_type) {
-                       case SCM_RIGHTS:
-                               if (fds != NULL)
-                                       fdnum = __get_descriptors(cmsg, &msg, fds, MAX_NR_OF_DESCRIPTORS);
-                               if (nr_fds != NULL)
-                                       *nr_fds = fdnum;
-                               break;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-int aul_sock_recv_reply_sock_fd(int fd, int (*ret_fd)[2], int fd_size)
-{
-       int fds[2] = {0,};
-       char recv_buff[1024];
-       struct iovec vec[3];
-       int ret = 0;
-       int vec_len = 0;
-       int fds_len = 0;
-
-       vec[0].iov_base = recv_buff;
-       vec[0].iov_len = sizeof(recv_buff);
-       ret = __recv_message(fd, vec, 1, &vec_len, fds, &fds_len);
-       if (ret < 0) {
-               _E("Error[%d]. while receiving message", -ret);
-               if (fds_len > 0)
-                       close(fds[0]);
-
-               ret = -ECOMM;
-       } else if ((fds_len == fd_size) && (fds_len == 2)) {
-               (*ret_fd)[0] = fds[0];
-               (*ret_fd)[1] = fds[1];
-       } else if ((fds_len == fd_size) && (fds_len == 1)) {
-               (*ret_fd)[0] = fds[0];
-       } else {
-               _E("wrong number of FD recevied. Expected:%d Actual:%d", fd_size, fds_len);
-               ret = -ECOMM;
-       }
-
-       close(fd);
-       return ret;
-}
-
-int aul_sock_create_launchpad_client(const char *pad_type, uid_t uid)
-{
-       int fd = -1;
-       struct sockaddr_un saddr = { 0, };
-       int retry = 1;
-       int ret = -1;
-
-       fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
-       /*  support above version 2.6.27*/
-       if (fd < 0) {
-               if (errno == EINVAL) {
-                       fd = socket(AF_UNIX, SOCK_STREAM, 0);
-                       if (fd < 0) {
-                               _E("second chance - socket create error");
-                               return -1;
-                       }
-               } else {
-                       _E("socket error");
-                       return -1;
-               }
-       }
-
-       saddr.sun_family = AF_UNIX;
-       snprintf(saddr.sun_path, sizeof(saddr.sun_path),
-                               "/run/aul/daemons/%d/%s", uid, pad_type);
-retry_con:
-       ret = __connect_client_sock(fd, (struct sockaddr *)&saddr,
-                               sizeof(saddr), 100 * 1000);
-       if (ret < -1) {
-               _E("maybe peer not launched or peer dead");
-               if (retry > 0) {
-                       usleep(100 * 1000);
-                       retry--;
-                       goto retry_con;
-               }
-       }
-       if (ret < 0) {
-               close(fd);
-               return -1;
-       }
-
-       aul_sock_set_sock_option(fd, 1);
-
-       return fd;
-}
-
-API int aul_sock_recv_pkt_with_cb(int fd,
-               void (*callback)(app_pkt_t *pkt, void *data),
-               void *user_data)
-{
-       app_pkt_t **pkt;
-       int count = 0;
-       size_t size;
-       int ret;
-       int i;
-
-       if (fd < 0 || fd >= sysconf(_SC_OPEN_MAX)) {
-               _E("Invalid parameter");
-               return -1;
-       }
-
-       if (callback == NULL) {
-               _E("Invalid parameter");
-               close(fd);
-               return -1;
-       }
-
-       ret = __recv_raw(fd, (unsigned char *)&count, sizeof(int));
-       if (ret < 0) {
-               _E("recv error - %d", ret);
-               close(fd);
-               return ret;
-       } else if (count <= 0 || count > MAX_RUNNING_INSTANCE) {
-               _E("error - count: %d", count);
-               close(fd);
-               return -ECOMM;
-       }
-
-       size = sizeof(app_pkt_t *) * count;
-       _D("count: %d, size: %zu", count, size);
-       pkt = (app_pkt_t **)calloc(1, size);
-       if (pkt == NULL) {
-               _E("out of memory");
-               close(fd);
-               return -1;
-       }
-
-       for (i = 0; i < count; ++i) {
-               ret = __recv_pkt(fd, &pkt[i]);
-               if (ret < 0) {
-                       _E("Failed to receive packet");
-                       break;
-               }
-       }
-
-       for (i = 0; i < count; ++i) {
-               callback(pkt[i], user_data);
-               free(pkt[i]);
-       }
-
-       free(pkt);
-       close(fd);
-
-       return ret;
-}
-
-API int aul_sock_recv_result_with_fd(int fd)
-{
-       int len;
-       int res;
-
-       len = __recv_raw(fd, (unsigned char *)&res, sizeof(int));
-       if (len < 0) {
-               _E("Failed to receive the result. fd(%d)", fd);
-               res = -ECOMM;
-       }
-
-       return res;
-}
-
-static void __delete_dir(const char *path)
-{
-       DIR *dp;
-       struct dirent *dentry = NULL;
-       char buf[PATH_MAX];
-       struct stat statbuf;
-       int ret;
-
-       if (path == NULL)
-               return;
-
-       dp = opendir(path);
-       if (dp == NULL)
-               return;
-
-       while ((dentry = readdir(dp)) != NULL) {
-               if (!strcmp(dentry->d_name, ".") ||
-                               !strcmp(dentry->d_name, ".."))
-                       continue;
-
-               snprintf(buf, sizeof(buf), "%s/%s", path, dentry->d_name);
-               ret = stat(buf, &statbuf);
-               if (ret == 0) {
-                       if (S_ISDIR(statbuf.st_mode))
-                               __delete_dir(buf);
-                       else
-                               unlink(buf);
-               }
-       }
-
-       rmdir(path);
-       closedir(dp);
-}
-
-API int aul_sock_destroy_server(int fd)
-{
-       char path[PATH_MAX];
-
-       if (fd > 3)
-               close(fd);
-
-       if (getuid() >= REGULAR_UID_MIN) {
-               snprintf(path, sizeof(path),
-                               "/run/aul/apps/%u/%d",
-                               getuid(), getpid());
-               __delete_dir(path);
-
-               if (socket_link_created) {
-                       __delete_dir(dirname(socket_link_path));
-                       socket_link_created = 0;
-               }
-       } else {
-               snprintf(path, sizeof(path),
-                               "/run/aul/daemons/%u/.app-sock-%d",
-                               getuid(), getpid());
-               unlink(path);
-
-               if (socket_link_created) {
-                       unlink(socket_link_path);
-                       socket_link_created = 0;
-               }
-       }
-
-       return 0;
-}
-
-API int aul_sock_send_result(int fd, int res)
-{
-       return aul_sock_send_result_v2(fd, res, true);
-}
-
-API int aul_sock_send_result_v2(int fd, int res, bool do_close)
-{
-       int ret;
-
-       if (fd < 0 || fd >= sysconf(_SC_OPEN_MAX)) {
-               _E("Invalid parameter");
-               return -EINVAL;
-       }
-
-       ret = send(fd, &res, sizeof(res), MSG_NOSIGNAL);
-       if (ret < 0)
-               _E("Failed to send result. fd(%d), errno(%d)", fd, errno);
-
-       if (do_close)
-               close(fd);
-
-       return ret;
-}
-
-API int aul_sock_recv_reply_pkt_v2(int fd, app_pkt_t **pkt, bool do_close)
-{
-       int ret;
-
-       if (fd < 0 || fd >= sysconf(_SC_OPEN_MAX))
-               return -EINVAL;
-
-       if (!pkt) {
-               if (do_close)
-                       close(fd);
-               return -EINVAL;
-       }
-
-       ret = __recv_pkt(fd, pkt);
-       if (do_close)
-               close(fd);
-
-       return ret;
-}
diff --git a/src/aul_sock.cc b/src/aul_sock.cc
new file mode 100644 (file)
index 0000000..893ee7d
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ * Copyright (c) 2000 - 2022 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 "include/aul_sock.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <tzplatform_config.h>
+#include <unistd.h>
+#include <vconf.h>
+
+#include <bundle_cpp.h>
+
+#include "aul_api.h"
+#include "aul_util.h"
+
+#include "aul/socket/client_socket.hh"
+#include "aul/socket/packet.hh"
+#include "aul/socket/server_socket.hh"
+
+using namespace aul;
+
+namespace {
+
+constexpr const int MAX_NR_OF_DESCRIPTORS = 2;
+constexpr const int MAX_PAYLOAD_SIZE = 1024 * 1024 * 1;
+constexpr const char PATH_AUL_SOCKET_TIMEOUT[] = "/run/aul/.socket_timeout";
+constexpr const char PATH_AMD_SOCK[] = "/run/aul/daemons/.amd-sock";
+int MAX_FDS = sysconf(_SC_OPEN_MAX);
+
+// POD type
+struct PacketHeader {
+  int cmd;
+  int len;
+  int opt;
+};
+
+class SocketTimeout {
+ public:
+  SocketTimeout() = default;
+
+  ~SocketTimeout() {
+    if (initialized_)
+      vconf_ignore_key_changed(VCONFKEY_AUL_SOCKET_TIMEOUT, VconfCb);
+  }
+
+  timeval GetTimeval() const {
+    return time_val_;
+  }
+
+  bool IsInitialized() const {
+    return initialized_;
+  }
+
+  void Init() {
+    if (access(PATH_AUL_SOCKET_TIMEOUT, F_OK) != 0) {
+      initialized_ = true;
+      return;
+    }
+
+    double timeout = 5.2f;
+    int ret = vconf_get_dbl(VCONFKEY_AUL_SOCKET_TIMEOUT, &timeout);
+    if (ret != VCONF_OK)
+      _E("vconf_get_dbl() is failed. error(%d)", ret);
+
+    ret = vconf_notify_key_changed(VCONFKEY_AUL_SOCKET_TIMEOUT, VconfCb, this);
+    if (ret != VCONF_OK)
+      _E("vconf_notify_key_changed() is failed. error(%d)", ret);
+
+    SetTimeout(timeout);
+    initialized_ = true;
+  }
+
+ private:
+  static void VconfCb(keynode_t* node, void* user_data) {
+    auto* h = static_cast<SocketTimeout*>(user_data);
+    double timeout = vconf_keynode_get_dbl(node);
+    h->SetTimeout(timeout);
+  }
+
+  void SetTimeout(double timeout) {
+    char buf[12];
+    snprintf(buf, sizeof(buf), "%.3f", timeout);
+    gchar* ptr = nullptr;
+    time_val_.tv_sec = g_ascii_strtoll(buf, &ptr, 10);
+    time_val_.tv_usec = g_ascii_strtoll(ptr + 1, &ptr, 10) * 1000;
+  }
+
+ private:
+  bool initialized_ = false;
+  timeval time_val_ = { 5, 200 * 1000 };
+};
+
+std::string GetSocketPath(pid_t pid, uid_t uid) {
+  if (pid == -2)
+    return std::string(PATH_AMD_SOCK);
+
+  char path[108];
+  if (uid < REGULAR_UID_MIN)
+    snprintf(path, sizeof(path), "/run/aul/daemons/%u/.app-sock-%d", uid, pid);
+  else
+    snprintf(path, sizeof(path), "/run/aul/apps/%u/%d/.app-sock", uid, pid);
+
+  return std::string(path);
+}
+
+int CreateSocketDirectory(pid_t pid, uid_t uid) {
+  std::string socket_path = GetSocketPath(pid, uid);
+  std::string path = dirname(const_cast<char*>(socket_path.c_str()));
+  if (mkdir(path.c_str(), 0700) != 0) {
+    if (errno == EEXIST) {
+      if (access(path.c_str(), R_OK) != 0) {
+        _E("access() is failed. path(%s), errno(%d)", path.c_str(), errno);
+        return -1;
+      }
+    } else {
+      _E("mkdir() is failed. path(%s), errno(%d)", path.c_str(), errno);
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+class SocketLink {
+ public:
+  SocketLink() = default;
+
+  void Create(const std::string& socket_path, pid_t pid, uid_t uid) {
+    if (CreateSocketDirectory(pid, uid) != 0)
+      return;
+
+    path_ = GetSocketPath(pid, uid);
+    if (link(socket_path.c_str(), path_.c_str()) != 0) {
+      _E("link() is failed. old(%s), new(%s), errno(%d)",
+          socket_path.c_str(), path_.c_str(), errno);
+    }
+
+    created_ = true;
+  }
+
+  void Delete() {
+    if (!created_)
+      return;
+
+    unlink(path_.c_str());
+    created_ = false;
+  }
+
+ private:
+  bool created_ = false;
+  std::string path_;
+};
+
+int SendAndReceive(ClientSocket* client, int cmd, unsigned char* data,
+    int datalen, int opt) {
+  _D("fd(%d), cmd(%d)", client->GetFd(), cmd);
+
+  Packet packet(cmd, opt, { data, data + datalen });
+  tizen_base::Parcel parcel;
+  parcel.WriteParcelable(packet);
+  auto raw = parcel.GetRaw();
+
+  int ret = client->Send(reinterpret_cast<void*>(&raw[0]), raw.size());
+  if (ret != 0 || opt & AUL_SOCK_NOREPLY) {
+    if (opt & AUL_SOCK_ASYNC)
+      client->RemoveFd();
+
+    return ret;
+  }
+
+  if (opt & AUL_SOCK_ASYNC)
+    return client->RemoveFd();
+
+  int res;
+  ret = client->Receive(reinterpret_cast<void*>(&res), sizeof(res));
+  if (ret < 0)
+    res = ret;
+
+  return res;
+}
+
+int SendAndReceive(int fd, int cmd, unsigned char* data, int datalen,
+    int opt) {
+  ClientSocket client(fd);
+  return SendAndReceive(&client, cmd, data, datalen, opt);
+}
+
+int SendAndReceive(int pid, uid_t uid, int cmd, unsigned char* data,
+    int datalen, int opt) {
+  int ret;
+  try {
+    ClientSocket client;
+    std::string endpoint = GetSocketPath(pid, uid);
+    client.Connect(endpoint);
+    aul_sock_set_sock_option(client.GetFd(), 1);
+
+    ret = SendAndReceive(&client, cmd, data, datalen, opt);
+  } catch (const Exception& e) {
+    _E("Exception occurs. error(%d)", e.GetErrorCode());
+    return e.GetErrorCode();
+  }
+
+  return ret;
+}
+
+int ReceiveAppPacket(ClientSocket* client, app_pkt_t** out_pkt) {
+  PacketHeader header;
+  static_assert(std::is_standard_layout<PacketHeader>(),
+      "PacketHeader should be POD type");
+  static_assert(std::is_trivial<PacketHeader>(),
+      "Header should be POD type");
+
+  *out_pkt = nullptr;
+  int ret = client->Receive(&header, sizeof(header));
+  if (ret < 0)
+    return ret;
+
+  app_pkt_t* pkt = static_cast<app_pkt_t*>(
+      calloc(1, sizeof(app_pkt_t) + header.len));
+  if (pkt == nullptr) {
+    _E("Out of memory");
+    return -ENOMEM;
+  }
+
+  pkt->cmd = header.cmd;
+  pkt->len = header.len;
+  pkt->opt = header.opt;
+
+  ret = client->Receive(pkt->data, pkt->len);
+  if (ret < 0) {
+    free(pkt);
+    return ret;
+  }
+
+  *out_pkt = pkt;
+  return 0;
+}
+
+int GetFileDescriptor(struct cmsghdr* cmsg, struct msghdr* msg, int* fds,
+    int maxdesc) {
+  if (cmsg == nullptr || msg == nullptr)
+    return 0;
+
+  if (cmsg->cmsg_type != SCM_RIGHTS)
+    return 0;
+
+  int retnr = 0;
+  if (msg->msg_controllen > 0) {
+    int payload = cmsg->cmsg_len - sizeof(*cmsg);
+    int* recvdesc = reinterpret_cast<int*>(CMSG_DATA(cmsg));
+    int nrdesc = payload / sizeof(int);
+    retnr = nrdesc < maxdesc ? nrdesc : maxdesc;
+    for (int i = 0; i < nrdesc; ++i) {
+      if (maxdesc-- > 0)
+        *fds++ = *recvdesc++;
+      else
+        close(*recvdesc++);
+    }
+  }
+
+  return retnr;
+}
+
+int ReceiveMessage(int fd, struct iovec* vec, int vec_max_size, int* vec_size,
+    int* fds, int* nr_fds) {
+  if (vec == nullptr || vec_max_size < 1 || vec_size == nullptr)
+    return -EINVAL;
+
+  char buf[CMSG_SPACE(sizeof(int) * MAX_NR_OF_DESCRIPTORS) + CMSG_SPACE(50)] = { 0, };
+  struct msghdr msg = { 0, };
+  msg.msg_iov = vec;
+  msg.msg_iovlen = vec_max_size;
+  msg.msg_control = buf;
+  msg.msg_controllen = sizeof(buf);
+
+  bool is_blocking;
+  if (fcntl(fd, F_GETFL, 0) & O_NONBLOCK)
+    is_blocking = false;
+  else
+    is_blocking = true;
+
+retry:
+  int ret = recvmsg(fd, &msg, 0);
+  if (ret == 0) {
+    _W("Socket was disconnected. fd(%d)", fd);
+    return -ECOMM;
+  }
+
+  if (ret < 0) {
+    if (errno == EINTR || errno == EAGAIN) {
+      if (is_blocking && errno == EAGAIN) {
+        _E("recvmsg() timed out. fd(%d)", fd);
+        return -EAGAIN;
+      }
+
+      usleep(100 * 1000);
+      goto retry;
+    }
+
+    ret = -errno;
+    _E("recvmsg() is failed. fd(%d), errno(%d)", fd, errno);
+    return ret;
+  }
+
+  *vec_size = msg.msg_iovlen;
+
+  struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+  if (cmsg == nullptr) {
+    if (nr_fds != nullptr)
+      *nr_fds = 0;
+  } else {
+    for (int i = 0; cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg), ++i) {
+      if (cmsg->cmsg_type == SCM_RIGHTS) {
+        if (fds != nullptr) {
+          int fdnum = GetFileDescriptor(cmsg, &msg, fds, MAX_NR_OF_DESCRIPTORS);
+          if (nr_fds != nullptr)
+            *nr_fds = fdnum;
+        }
+      }
+    }
+  }
+
+  return 0;
+}
+
+void DeleteDirectories(const std::string& path) {
+  if (path.empty())
+    return;
+
+  DIR* dp = opendir(path.c_str());
+  if (dp == nullptr)
+    return;
+
+  struct stat statbuf;
+  struct dirent* dentry = nullptr;
+  while ((dentry = readdir(dp)) != nullptr) {
+    if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
+      continue;
+
+    std::string entry = path + dentry->d_name;
+    if (stat(entry.c_str(), &statbuf) == 0) {
+      if (S_ISDIR(statbuf.st_mode))
+        DeleteDirectories(entry);
+      else
+        unlink(entry.c_str());
+    }
+  }
+
+  rmdir(path.c_str());
+  closedir(dp);
+}
+
+SocketTimeout socket_timeout;
+SocketLink socket_link;
+
+}  // namespace
+
+extern "C" API struct timeval aul_sock_get_rcv_timeout(void) {
+  return socket_timeout.GetTimeval();
+}
+
+extern "C" API int aul_sock_set_sock_option(int fd, int cli) {
+  int size = AUL_SOCK_MAXBUFF;
+  int ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
+  if (ret != 0)
+    return ret;
+
+  ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
+  if (ret != 0)
+    return ret;
+
+  if (cli) {
+    if (TIZEN_FEATURE_SOCKET_TIMEOUT && !socket_timeout.IsInitialized())
+      socket_timeout.Init();
+
+    auto timeout = socket_timeout.GetTimeval();
+    ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+    if (ret != 0)
+      return ret;
+  }
+
+  return 0;
+}
+
+extern "C" API int aul_sock_create_server(int pid, uid_t uid) {
+  auto path = GetSocketPath(pid, uid);
+  int fd = -1;
+  try {
+    if (CreateSocketDirectory(pid, uid) != 0)
+      return -1;
+
+    ServerSocket socket;
+    socket.Bind(path);
+    aul_sock_set_sock_option(socket.GetFd(), 0);
+    socket.Listen(128);
+    fd = socket.RemoveFd();
+  } catch (const Exception& e) {
+    _E("Exception occurs. error(%d)", e.GetErrorCode());
+    return e.GetErrorCode();
+  }
+
+  if (pid > 0) {
+    pid_t aul_pid;
+    const char* aul_pid_str = getenv("AUL_PID");
+    if (aul_pid_str != nullptr && isdigit(aul_pid_str[0]))
+      aul_pid = atoi(aul_pid_str);
+    else
+      aul_pid = -1;
+
+    if (aul_pid > 1 && aul_pid != pid)
+      socket_link.Create(path.c_str(), aul_pid, uid);
+  }
+
+  return fd;
+}
+
+extern "C" API int aul_sock_send_raw_with_fd(int fd, int cmd,
+    unsigned char* kb_data, int datalen, int opt) {
+  return SendAndReceive(fd, cmd, kb_data, datalen, opt);
+}
+
+extern "C" API int aul_sock_send_bundle_with_fd(int fd, int cmd, bundle* kb,
+    int opt) {
+  if (kb == nullptr)
+    return -EINVAL;
+
+  tizen_base::Bundle b(kb, false, false);
+  auto raw = b.ToRaw();
+  return SendAndReceive(fd, cmd,
+      reinterpret_cast<unsigned char*>(raw.first.get()),
+      raw.second, opt | AUL_SOCK_BUNDLE);
+}
+
+extern "C" API int aul_sock_send_raw(int pid, uid_t uid, int cmd,
+    unsigned char* kb_data, int datalen, int opt) {
+  return SendAndReceive(pid, uid, cmd, kb_data, datalen, opt);
+}
+
+extern "C" API int aul_sock_send_bundle(int pid, uid_t uid, int cmd,
+    bundle* kb, int opt) {
+  if (kb == nullptr)
+    return -EINVAL;
+
+  tizen_base::Bundle b(kb, false, false);
+  auto raw = b.ToRaw();
+  return SendAndReceive(pid, uid, cmd,
+      reinterpret_cast<unsigned char*>(raw.first.get()), raw.second,
+      opt | AUL_SOCK_BUNDLE);
+}
+
+extern "C" API app_pkt_t* aul_sock_recv_pkt(int fd, int* clifd,
+    struct ucred* cred) {
+  ServerSocket server(fd);
+  auto client = std::unique_ptr<ClientSocket>(server.Accept());
+  server.RemoveFd();
+  if (client.get() == nullptr)
+    return nullptr;
+
+  socklen_t optlen = sizeof(struct ucred);
+  int ret = getsockopt(client->GetFd(), SOL_SOCKET, SO_PEERCRED,
+      cred, &optlen);
+  if (ret < 0) {
+    _E("getsockopt() is failed. errno(%d)", errno);
+    return nullptr;
+  }
+
+  aul_sock_set_sock_option(client->GetFd(), 1);
+
+  app_pkt_t* pkt = nullptr;
+  ret = ReceiveAppPacket(client.get(), &pkt);
+  if (ret < 0)
+    return nullptr;
+
+  *clifd = client->RemoveFd();
+  return pkt;
+}
+
+extern "C" API int aul_sock_recv_reply_pkt(int fd, app_pkt_t** ret_pkt) {
+  return aul_sock_recv_reply_pkt_v2(fd, ret_pkt, true);
+}
+
+extern "C" API int aul_sock_recv_reply_sock_fd(int fd, int (*ret_fd)[2],
+    int fd_size) {
+  int fds[2] = { -1, -1 };
+  int vec_len = 0;
+  int fds_len = 0;
+  char recv_buff[1024] = { 0, };;
+  struct iovec vec[3] = { 0, };
+  vec[0].iov_base = recv_buff;
+  vec[0].iov_len = sizeof(recv_buff);
+  int ret = ReceiveMessage(fd, vec, 1, &vec_len, fds, &fds_len);
+  if (ret < 0) {
+    _E("ReceiveMessage() is failed. error(%d)", ret);
+    if (fds_len > 0)
+      close(fds[0]);
+
+    ret = -ECOMM;
+  } else if (fds_len == fd_size && fds_len == 2) {
+    (*ret_fd)[0] = fds[0];
+    (*ret_fd)[1] = fds[1];
+  } else if (fds_len == fd_size && fds_len == 1) {
+    (*ret_fd)[0] = fds[0];
+  } else {
+    _E("Wrong number of FD received. Expected: %d, Actual: %d",
+        fd_size, fds_len);
+    ret = -ECOMM;
+  }
+
+  close(fd);
+  return ret;
+}
+
+extern "C" API int aul_sock_create_launchpad_client(const char* pad_type,
+    uid_t uid) {
+  int fd = -1;
+  try {
+    ClientSocket client;
+    std::string endpoint = "/run/aul/daemons/" + std::to_string(uid) + "/" +
+        std::string(pad_type);
+    client.Connect(endpoint);
+    fd = client.RemoveFd();
+    aul_sock_set_sock_option(fd, 1);
+  } catch (const Exception& e) {
+    _E("Exception occurs. error(%d)", e.GetErrorCode());
+    return e.GetErrorCode();
+  }
+
+  return fd;
+}
+
+extern "C" API int aul_sock_recv_pkt_with_cb(int fd,
+    void (*callback)(app_pkt_t* pkt, void* user_data),
+    void* user_data) {
+  if (fd < 0 || fd >= MAX_FDS) {
+    _E("Invalid parameter");
+    return -1;
+  }
+
+  if (callback == nullptr) {
+    _E("Invalid parameter");
+    close(fd);
+    return -1;
+  }
+
+  ClientSocket client(fd);
+  int count = 0;
+  int ret = client.Receive(&count, sizeof(count));
+  if (ret != 0) {
+    _E("Receive() is failed. error(%d)", ret);
+    return ret;
+  }
+
+  if (count <= 0 || count > MAX_RUNNING_INSTANCE) {
+    _E("Error occurs. count(%d)", count);
+    return -ECOMM;
+  }
+
+  app_pkt_t** pkt = reinterpret_cast<app_pkt_t**>(
+      calloc(count, sizeof(app_pkt_t*)));
+  if (pkt == nullptr) {
+    _E("Out of memory");
+    return -ENOMEM;
+  }
+
+  for (int i = 0; i < count; ++i) {
+    ret = ReceiveAppPacket(&client, &pkt[i]);
+    if (ret != 0) {
+      _E("ReceiveAppPacket() is failed. error(%d)", ret);
+      break;
+    }
+  }
+
+  for (int i = 0; i < count; ++i) {
+    if (pkt[i] != nullptr) {
+      callback(pkt[i], user_data);
+      free(pkt[i]);
+    }
+  }
+
+  free(pkt);
+  return ret;
+}
+
+extern "C" API int aul_sock_recv_result_with_fd(int fd) {
+  ClientSocket client(fd);
+  int res;
+  int ret = client.Receive(&res, sizeof(res));
+  client.RemoveFd();
+  if (ret < 0) {
+    _E("Receive() is failed. fd(%d), error(%d)", fd, ret);
+    res = -ECOMM;
+  }
+
+  return res;
+}
+
+extern "C" API int aul_sock_destroy_server(int fd) {
+  if (fd > -1)
+    close(fd);
+
+  if (getuid() < REGULAR_UID_MIN) {
+    std::string path = "/run/aul/daemons/" + std::to_string(getuid()) +
+        "/.app-sock-" + std::to_string(getpid());
+    unlink(path.c_str());
+  } else {
+    std::string path = "/run/aul/apps/" + std::to_string(getuid()) + "/" +
+        std::to_string(getpid());
+    DeleteDirectories(path);
+  }
+  socket_link.Delete();
+
+  return 0;
+}
+
+extern "C" API int aul_sock_send_result(int fd, int res) {
+  return aul_sock_send_result_v2(fd, res, true);
+}
+
+extern "C" API int aul_sock_send_result_v2(int fd, int res, bool do_close) {
+  if (fd < 0 || fd >= MAX_FDS) {
+    _E("Invalid parameter");
+        return -EINVAL;
+  }
+
+  int ret = send(fd, &res, sizeof(res), MSG_NOSIGNAL);
+  if (ret < 0)
+    _E("send() is failed. fd(%d), errno(%d)", fd, errno);
+
+  if (do_close)
+    close(fd);
+
+  return ret;
+}
+
+extern "C" API int aul_sock_recv_reply_pkt_v2(int fd, app_pkt_t** pkt,
+    bool do_close) {
+  if (fd < 0 || fd >= MAX_FDS)
+    return -EINVAL;
+
+  if (pkt == nullptr) {
+    if (do_close)
+      close(fd);
+
+    return -EINVAL;
+  }
+
+  ClientSocket client(fd);
+  int ret = ReceiveAppPacket(&client, pkt);
+  if (!do_close)
+    client.RemoveFd();
+
+  return ret;
+}
index b3b4e12..193fd2a 100644 (file)
@@ -5,19 +5,16 @@
 #include <gtest/gtest.h>
 #include <gmock/gmock.h>
 
-//#define LOG_INTERNAL
-
 #include <dlog.h>
 
-extern "C" int __dlog_print(log_id_t log_id, int prio, const char *tag, const char *fmt, ...) {
-#ifdef LOG_INTERNAL
+extern "C" int __dlog_print(log_id_t log_id, int prio, const char* tag,
+    const char* fmt, ...) {
   printf("%s:", tag);
   va_list ap;
   va_start(ap, fmt);
   vprintf(fmt, ap);
   va_end(ap);
   printf("\n");
-#endif
   return 0;
 }