Release version 0.15.20
[platform/core/appfw/launchpad.git] / src / lib / common / src / launchpad_socket.c
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #define _GNU_SOURCE
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/socket.h>
24 #include <sys/types.h>
25 #include <sys/un.h>
26 #include <unistd.h>
27
28 #include "launchpad_socket.h"
29 #include "log_private.h"
30
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
35
36 struct socket_s {
37         char *path;
38         bool client;
39         int fd;
40         int pid;
41 };
42
43 static int __set_socket_option(int fd, bool client)
44 {
45         struct timeval tv = { 5, 200 * 1000 };  /*  5.2 sec */
46         int size = LAUNCHPAD_SOCKET_MAX_BUFF;
47         int flag;
48         int ret;
49
50         ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
51         if (ret < 0) {
52                 ret = -errno;
53                 _E("setsockopt(SO_SNDBUF) is failed. fd(%d), errno(%d)",
54                                 fd, errno);
55                 return ret;
56         }
57
58         ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
59         if (ret < 0) {
60                 ret = -errno;
61                 _E("setsockopt(SO_RCVBUF) is failed. fd(%d), errno(%d)",
62                                 fd, errno);
63                 return ret;
64         }
65
66         if (!client)
67                 return 0;
68
69         ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
70         if (ret < 0) {
71                 ret = -errno;
72                 _E("setsockopt(SO_RCVTIMEO) is failed. fd(%d), errno(%d)",
73                                 fd, errno);
74                 return ret;
75         }
76
77         flag = fcntl(fd, F_GETFD);
78         flag |= FD_CLOEXEC;
79         ret = fcntl(fd, F_SETFD, flag);
80         if (ret < 0) {
81                 ret = -errno;
82                 _E("fcntl(F_SETFD) is failed. fd(%d), errno(%d)", fd, errno);
83                 return ret;
84         }
85
86         return 0;
87 }
88
89 static int __create_server_socket(const char *path)
90 {
91         struct sockaddr_un addr = { 0, };
92         int ret;
93         int fd;
94
95         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
96         if (fd < 0) {
97                 ret = -errno;
98                 _E("socket() is failed. path(%s), errno(%d)", path, errno);
99                 return ret;
100         }
101
102         addr.sun_family = AF_UNIX;
103         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
104         unlink(addr.sun_path);
105
106         ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
107         if (ret < 0) {
108                 ret = -errno;
109                 _E("bind() is failed. path(%s), errno(%d)", path, errno);
110                 close(fd);
111                 return ret;
112         }
113
114         ret = __set_socket_option(fd, false);
115         if (ret < 0) {
116                 close(fd);
117                 return ret;
118         }
119
120         ret = listen(fd, LAUNCHPAD_SOCKET_MAX_PENDING_CONNECTION);
121         if (ret < 0) {
122                 ret = -errno;
123                 _E("listen() is failed. path(%s), errno(%d)", path, errno);
124                 close(fd);
125                 return ret;
126         }
127
128         return fd;
129 }
130
131 static int __create_client_socket(const char *path)
132 {
133         struct sockaddr_un addr = { 0, };
134         int retry = LAUNCHPAD_SOCKET_RETRY_COUNT;
135         int ret;
136         int fd;
137
138         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
139         if (fd < 0) {
140                 ret = -errno;
141                 _E("socket() is failed. path(%s), errno(%d)", path, errno);
142                 return ret;
143         }
144
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) {
149                         ret = -errno;
150                         _E("connect() is failed. path(%s), errno(%d)",
151                                         path, errno);
152                         close(fd);
153                         return ret;
154                 }
155
156                 usleep(LAUNCHPAD_SOCKET_RETRY_TIME);
157                 retry--;
158                 _W("Retry(%d) to connect to %s", retry, path);
159         }
160
161         ret = __set_socket_option(fd, true);
162         if (ret < 0) {
163                 close(fd);
164                 return ret;
165         }
166
167         return fd;
168 }
169
170 static void __destroy_socket(struct socket_s *sock)
171 {
172         if (!sock)
173                 return;
174
175         if (!sock->client && sock->fd > 0 && sock->path)
176                 unlink(sock->path);
177
178         free(sock->path);
179         free(sock);
180 }
181
182 static struct socket_s *__create_socket(const char *path, bool client,
183                 int fd, int pid)
184 {
185         struct socket_s *sock;
186
187         sock = calloc(1, sizeof(struct socket_s));
188         if (!sock) {
189                 _E("Out of memory");
190                 return NULL;
191         }
192
193         if (path) {
194                 sock->path = strdup(path);
195                 if (!sock->path) {
196                         _E("Failed to duplicate socket path(%s)", path);
197                         __destroy_socket(sock);
198                         return NULL;
199                 }
200         }
201
202         sock->client = client;
203         sock->fd = fd;
204         sock->pid = pid;
205
206         return sock;
207 }
208
209 int _socket_create(const char *path, bool client, socket_h *handle)
210 {
211         struct socket_s *sock;
212         int fd;
213
214         if (!path || !handle) {
215                 _E("Invalid parameter");
216                 return -EINVAL;
217         }
218
219         if (client)
220                 fd = __create_client_socket(path);
221         else
222                 fd = __create_server_socket(path);
223
224         if (fd < 0)
225                 return fd;
226
227         sock = __create_socket(path, client, fd, getpid());
228         if (!sock) {
229                 close(fd);
230                 return -ENOMEM;
231         }
232
233         *handle = sock;
234
235         return 0;
236 }
237
238 int _socket_create_with_fd(int fd, socket_h *handle)
239 {
240         struct socket_s *sock;
241
242         if (fd < 0 || !handle) {
243                 _E("Invalid parameter");
244                 return -EINVAL;
245         }
246
247         sock = __create_socket(NULL, true, fd, getpid());
248         if (!sock)
249                 return -ENOMEM;
250
251         *handle = sock;
252
253         return 0;
254 }
255
256 int _socket_destroy(socket_h handle)
257 {
258         if (!handle) {
259                 _E("Invalid parameter");
260                 return -EINVAL;
261         }
262
263         if (handle->fd > 0)
264                 close(handle->fd);
265
266         __destroy_socket(handle);
267
268         return 0;
269 }
270
271 int _socket_accept(socket_h handle, socket_h *client_socket)
272 {
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);
278         int client_fd;
279         int ret;
280
281         if (!handle || !client_socket) {
282                 _E("Invalid parameter");
283                 return -EINVAL;
284         }
285
286         client_fd = accept(handle->fd, (struct sockaddr *)&addr, &addr_size);
287         if (client_fd < 0) {
288                 ret = -errno;
289                 _E("accept() is failed. errno(%d)", errno);
290                 return ret;
291         }
292
293         ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &cred_size);
294         if (ret < 0) {
295                 ret = -errno;
296                 _E("getsockopt(SO_PEERCRED) is failed. errno(%d)", errno);
297                 close(client_fd);
298                 return ret;
299         }
300
301         ret = __set_socket_option(client_fd, true);
302         if (ret < 0) {
303                 close(client_fd);
304                 return ret;
305         }
306
307         sock = __create_socket(NULL, true, client_fd, cred.pid);
308         if (!sock) {
309                 close(client_fd);
310                 return -ENOMEM;
311         }
312
313         *client_socket = sock;
314
315         return 0;
316 }
317
318 int _socket_get_fd(socket_h handle, int *fd)
319 {
320         if (!handle || !fd) {
321                 _E("Invalid parameter");
322                 return -EINVAL;
323         }
324
325         *fd = handle->fd;
326
327         return 0;
328 }
329
330 int _socket_set_fd(socket_h handle, int fd)
331 {
332         if (!handle) {
333                 _E("Invalid parameter");
334                 return -EINVAL;
335         }
336
337         handle->fd = fd;
338
339         return 0;
340 }
341
342 int _socket_get_pid(socket_h handle, int *pid)
343 {
344         if (!handle || !pid) {
345                 _E("Invalid parameter");
346                 return -EINVAL;
347         }
348
349         *pid = handle->pid;
350
351         return 0;
352 }
353
354 int _socket_send(socket_h handle, const void *buf, unsigned int size)
355 {
356         unsigned char *buffer = (unsigned char *)buf;
357         unsigned int left = size;
358         ssize_t write_size;
359         int ret;
360
361         if (!handle || !buf || !size) {
362                 _E("Invalid parameter");
363                 return -EINVAL;
364         }
365
366         while (left) {
367                 write_size = send(handle->fd, buffer, left, MSG_NOSIGNAL);
368                 if (write_size < 0) {
369                         ret = -errno;
370                         _E("send() is failed. fd(%d), errno(%d)",
371                                         handle->fd, errno);
372                         return ret;
373                 }
374
375                 left -= write_size;
376                 buffer += write_size;
377         }
378
379         return 0;
380 }
381
382 int _socket_read(socket_h handle, void *buf, unsigned int size)
383 {
384         unsigned char *buffer = (unsigned char *)buf;
385         unsigned int left = size;
386         ssize_t read_size;
387
388         if (!handle || !buf || !size) {
389                 _E("Invalid parameter");
390                 return -EINVAL;
391         }
392
393         while (left) {
394                 read_size = read(handle->fd, buffer, left);
395                 if (read_size == 0) {
396                         _W("EOF. fd(%d)", handle->fd);
397                         return -EIO;
398                 } else if (read_size < 0) {
399                         return -errno;
400                 }
401
402                 left -= read_size;
403                 buffer += read_size;
404         }
405
406         return 0;
407 }