2 * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <sys/socket.h>
24 #include <sys/types.h>
28 #include "launchpad_socket.h"
29 #include "log_private.h"
31 #define LAUNCHPAD_SOCKET_MAX_BUFF 131071
32 #define LAUNCHPAD_SOCKET_RETRY_TIME (100 * 1000)
33 #define LAUNCHPAD_SOCKET_RETRY_COUNT 3
34 #define LAUNCHPAD_SOCKET_MAX_PENDING_CONNECTION 128
43 static int __set_socket_option(int fd, bool client)
45 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
46 int size = LAUNCHPAD_SOCKET_MAX_BUFF;
50 ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
53 _E("setsockopt(SO_SNDBUF) is failed. fd(%d), errno(%d)",
58 ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
61 _E("setsockopt(SO_RCVBUF) is failed. fd(%d), errno(%d)",
69 ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
72 _E("setsockopt(SO_RCVTIMEO) is failed. fd(%d), errno(%d)",
77 flag = fcntl(fd, F_GETFD);
79 ret = fcntl(fd, F_SETFD, flag);
82 _E("fcntl(F_SETFD) is failed. fd(%d), errno(%d)", fd, errno);
89 static int __create_server_socket(const char *path)
91 struct sockaddr_un addr = { 0, };
95 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
98 _E("socket() is failed. path(%s), errno(%d)", path, errno);
102 addr.sun_family = AF_UNIX;
103 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
104 unlink(addr.sun_path);
106 ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
109 _E("bind() is failed. path(%s), errno(%d)", path, errno);
114 ret = __set_socket_option(fd, false);
120 ret = listen(fd, LAUNCHPAD_SOCKET_MAX_PENDING_CONNECTION);
123 _E("listen() is failed. path(%s), errno(%d)", path, errno);
131 static int __create_client_socket(const char *path)
133 struct sockaddr_un addr = { 0, };
134 int retry = LAUNCHPAD_SOCKET_RETRY_COUNT;
138 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
141 _E("socket() is failed. path(%s), errno(%d)", path, errno);
145 addr.sun_family = AF_UNIX;
146 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
147 while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
148 if (errno != ETIMEDOUT || retry <= 0) {
150 _E("connect() is failed. path(%s), errno(%d)",
156 usleep(LAUNCHPAD_SOCKET_RETRY_TIME);
158 _W("Retry(%d) to connect to %s", retry, path);
161 ret = __set_socket_option(fd, true);
170 static void __destroy_socket(struct socket_s *sock)
175 if (!sock->client && sock->fd > 0 && sock->path)
182 static struct socket_s *__create_socket(const char *path, bool client,
185 struct socket_s *sock;
187 sock = calloc(1, sizeof(struct socket_s));
194 sock->path = strdup(path);
196 _E("Failed to duplicate socket path(%s)", path);
197 __destroy_socket(sock);
202 sock->client = client;
209 int _socket_create(const char *path, bool client, socket_h *handle)
211 struct socket_s *sock;
214 if (!path || !handle) {
215 _E("Invalid parameter");
220 fd = __create_client_socket(path);
222 fd = __create_server_socket(path);
227 sock = __create_socket(path, client, fd, getpid());
238 int _socket_create_with_fd(int fd, socket_h *handle)
240 struct socket_s *sock;
242 if (fd < 0 || !handle) {
243 _E("Invalid parameter");
247 sock = __create_socket(NULL, true, fd, getpid());
256 int _socket_destroy(socket_h handle)
259 _E("Invalid parameter");
266 __destroy_socket(handle);
271 int _socket_accept(socket_h handle, socket_h *client_socket)
273 struct socket_s *sock;
274 struct sockaddr_un addr = { 0, };
275 struct ucred cred = { 0, };
276 socklen_t addr_size = sizeof(struct sockaddr_un);
277 socklen_t cred_size = sizeof(struct ucred);
281 if (!handle || !client_socket) {
282 _E("Invalid parameter");
286 client_fd = accept(handle->fd, (struct sockaddr *)&addr, &addr_size);
289 _E("accept() is failed. errno(%d)", errno);
293 ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &cred_size);
296 _E("getsockopt(SO_PEERCRED) is failed. errno(%d)", errno);
301 ret = __set_socket_option(client_fd, true);
307 sock = __create_socket(NULL, true, client_fd, cred.pid);
313 *client_socket = sock;
318 int _socket_get_fd(socket_h handle, int *fd)
320 if (!handle || !fd) {
321 _E("Invalid parameter");
330 int _socket_set_fd(socket_h handle, int fd)
333 _E("Invalid parameter");
342 int _socket_get_pid(socket_h handle, int *pid)
344 if (!handle || !pid) {
345 _E("Invalid parameter");
354 int _socket_send(socket_h handle, const void *buf, unsigned int size)
356 unsigned char *buffer = (unsigned char *)buf;
357 unsigned int left = size;
361 if (!handle || !buf || !size) {
362 _E("Invalid parameter");
367 write_size = send(handle->fd, buffer, left, MSG_NOSIGNAL);
368 if (write_size < 0) {
370 _E("send() is failed. fd(%d), errno(%d)",
376 buffer += write_size;
382 int _socket_read(socket_h handle, void *buf, unsigned int size)
384 unsigned char *buffer = (unsigned char *)buf;
385 unsigned int left = size;
388 if (!handle || !buf || !size) {
389 _E("Invalid parameter");
394 read_size = read(handle->fd, buffer, left);
395 if (read_size == 0) {
396 _W("EOF. fd(%d)", handle->fd);
398 } else if (read_size < 0) {