Merge branch 'devel/tizen' into tizen
[platform/core/system/sensord.git] / src / shared / socket.cpp
1 /*
2  * sensord
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include "socket.h"
21
22 #include <fcntl.h>
23 #include <sys/un.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
28 #include <systemd/sd-daemon.h>
29
30 #include "sensor_log.h"
31
32 using namespace ipc;
33
34 static bool set_close_on_exec(int fd)
35 {
36         if (::fcntl(fd, F_SETFL, FD_CLOEXEC) == -1)
37                 return false;
38
39         return true;
40 }
41
42 static int create_systemd_socket(const std::string &path, int type)
43 {
44         int n;
45         int listening;
46
47         listening = (type == SOCK_STREAM) ? 1 : -1;
48
49         n = sd_listen_fds(0);
50         retvm_if(n < 0, -EPERM, "Failed to listen fds from systemd");
51
52         for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) {
53                 if (sd_is_socket_unix(fd, type, listening, path.c_str(), 0) > 0) {
54                         set_close_on_exec(fd);
55                         return fd;
56                 }
57         }
58
59         return -EPERM;
60 }
61
62 static int create_unix_socket(int type)
63 {
64         int sock_fd = ::socket(AF_UNIX, type, 0);
65
66         if (sock_fd < 0) {
67                 _ERRNO(errno, _E, "Failed to create socket");
68                 return -EPERM;
69         }
70
71         set_close_on_exec(sock_fd);
72
73         int optval = 1;
74         if (::setsockopt(sock_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
75                 _ERRNO(errno, _E, "Failed to create socket[%d]", sock_fd);
76                 ::close(sock_fd);
77                 return -EPERM;
78         }
79
80         return sock_fd;
81 }
82
83 static bool select_fds(int fd, fd_set *read_fds, fd_set *write_fds, const int timeout)
84 {
85         struct timeval tv;
86         int err;
87
88         tv.tv_sec = timeout;
89         tv.tv_usec = 0;
90
91         while (true) {
92                 err = ::select(fd + 1, read_fds, write_fds, NULL, &tv);
93                 if (err <= 0)
94                         return false;
95
96                 if (read_fds && FD_ISSET(fd, read_fds))
97                         break;
98                 if (write_fds && FD_ISSET(fd, write_fds))
99                         break;
100         }
101
102         return true;
103 }
104
105 socket::socket()
106 : m_sock_fd(-1)
107 , m_mode(MSG_DONTWAIT | MSG_NOSIGNAL)
108 , m_listening(false)
109 {
110 }
111
112 socket::socket(int sock_fd)
113 : m_sock_fd(sock_fd)
114 , m_mode(MSG_DONTWAIT | MSG_NOSIGNAL)
115 , m_listening(false)
116 {
117 }
118
119 socket::socket(const socket &sock)
120 : m_sock_fd(-1)
121 , m_mode(MSG_DONTWAIT | MSG_NOSIGNAL)
122 , m_listening(false)
123 {
124         if (this == &sock)
125                 return;
126
127         m_sock_fd = sock.m_sock_fd;
128         m_mode = sock.m_mode;
129         m_listening.store(sock.m_listening);
130 }
131
132 socket::~socket()
133 {
134         close();
135 }
136
137 bool socket::connect(void)
138 {
139         const int TIMEOUT = 3;
140         sockaddr_un addr;
141         fd_set write_fds;
142         FD_ZERO(&write_fds);
143         FD_SET(m_sock_fd, &write_fds);
144
145         retvm_if(m_path.size() >= sizeof(sockaddr_un::sun_path), false,
146                         "Failed to create socket[%s]", m_path.c_str());
147
148         addr.sun_family = AF_UNIX;
149         strncpy(addr.sun_path, m_path.c_str(), sizeof(sockaddr_un::sun_path));
150         addr.sun_path[m_path.size()] = '\0';
151
152         if (::connect(m_sock_fd,
153                                 reinterpret_cast<struct sockaddr *>(&addr),
154                                 sizeof(struct sockaddr_un)) < 0) {
155                 _ERRNO(errno, _E, "Failed to connect() for socket[%d]", m_sock_fd);
156                 close();
157                 return false;
158         }
159
160         if (!select_fds(m_sock_fd, NULL, &write_fds, TIMEOUT)) {
161                 _E("Failed to select for socket[%d]", m_sock_fd);
162                 close();
163                 return false;
164         }
165
166         if (!has_connected()) {
167                 close();
168                 return false;
169         }
170
171         _D("Connected[%d]", m_sock_fd);
172
173         return true;
174 }
175
176 bool socket::bind(void)
177 {
178         sockaddr_un addr;
179         int file_mode;
180
181         retvm_if(m_path.size() >= sizeof(sockaddr_un::sun_path), false,
182                         "Failed to create socket[%s]", m_path.c_str());
183         retv_if(m_listening.load(), true);
184
185         if (!access(m_path.c_str(), F_OK))
186                 unlink(m_path.c_str());
187
188         addr.sun_family = AF_UNIX;
189         ::strncpy(addr.sun_path, m_path.c_str(), sizeof(sockaddr_un::sun_path));
190         addr.sun_path[m_path.size()] = '\0';
191
192         if (::bind(m_sock_fd,
193                                 reinterpret_cast<struct sockaddr *>(&addr),
194                                 sizeof(struct sockaddr_un)) < 0) {
195                 _ERRNO(errno, _E, "Failed to bind for socket[%d]", m_sock_fd);
196                 close();
197                 return false;
198         }
199
200         /* TODO: Is this really necessary? */
201         file_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
202         if (chmod(m_path.c_str(), file_mode) < 0) {
203                 _ERRNO(errno, _E, "Failed to create socket[%d]", m_sock_fd);
204                 close();
205                 return false;
206         }
207
208         _D("Bound to path[%d, %s]", m_sock_fd, m_path.c_str());
209
210         return true;
211 }
212
213 bool socket::listen(const int max_connections)
214 {
215         retv_if(m_listening.load(), true);
216
217         if (::listen(m_sock_fd, max_connections) < 0) {
218                 _ERRNO(errno, _E, "Failed to listen() for socket[%d]", m_sock_fd);
219                 close();
220                 return false;
221         }
222
223         m_listening.store(true);
224
225         _D("Listened[%d]", m_sock_fd);
226
227         return true;
228 }
229
230 bool socket::accept(socket &client_sock)
231 {
232         int fd;
233         fd_set read_fds;
234         FD_ZERO(&read_fds);
235         FD_SET(m_sock_fd, &read_fds);
236
237         fd = ::accept(m_sock_fd, NULL, NULL);
238
239         if (fd < 0) {
240                 _ERRNO(errno, _E, "Failed to accept[%d]", m_sock_fd);
241                 return false;
242         }
243
244         set_close_on_exec(fd);
245         client_sock.set_fd(fd);
246         /* TODO : socket type should be adjusted here */
247
248         _D("Accepted[%d, %d]", m_sock_fd, fd);
249
250         return true;
251 }
252
253 bool socket::close(void)
254 {
255         retv_if(m_sock_fd < 0, false);
256
257         if (::close(m_sock_fd) < 0)
258                 return false;
259
260         _D("Closed[%d]", m_sock_fd);
261
262         m_sock_fd = -1;
263         m_listening.store(false);
264
265         return true;
266 }
267
268 int socket::get_fd(void) const
269 {
270         return m_sock_fd;
271 }
272
273 void socket::set_fd(int sock_fd)
274 {
275         m_sock_fd = sock_fd;
276 }
277
278 int socket::get_mode(void) const
279 {
280         return m_mode;
281 }
282
283 bool socket::set_mode(int mode)
284 {
285         /* TODO : implement send/recv message mode */
286         return true;
287 }
288
289 bool socket::create(const std::string &path)
290 {
291         return false;
292 }
293
294 ssize_t socket::send(const void *buffer, size_t size, bool select) const
295 {
296         if (select) {
297                 const int TIMEOUT = 1;
298                 fd_set write_fds;
299                 FD_ZERO(&write_fds);
300                 FD_SET(m_sock_fd, &write_fds);
301
302                 if (!select_fds(m_sock_fd, NULL, &write_fds, TIMEOUT)) {
303                         _E("Failed to send message(timeout)");
304                         return 0;
305                 }
306         }
307
308         return on_send(buffer, size);
309 }
310
311 ssize_t socket::recv(void* buffer, size_t size, bool select) const
312 {
313         if (select) {
314                 const int TIMEOUT = 1;
315                 fd_set read_fds;
316                 FD_ZERO(&read_fds);
317                 FD_SET(m_sock_fd, &read_fds);
318
319                 if (!select_fds(m_sock_fd, &read_fds, NULL, TIMEOUT)) {
320                         _E("Failed to receive message(timeout)");
321                         return 0;
322                 }
323         }
324
325         return on_recv(buffer, size);
326 }
327
328 bool socket::create_by_type(const std::string &path, int type)
329 {
330         m_sock_fd = ::create_systemd_socket(path, type);
331         if (m_sock_fd < 0) {
332                 _D("Creating the UDS instead of systemd socket..");
333                 m_sock_fd = create_unix_socket(type);
334         } else {
335                 m_listening.store(true);
336         }
337
338         retvm_if((m_sock_fd < 0), false, "Failed to create socket");
339
340         /* non-blocking mode */
341         retvm_if(!set_blocking_mode(false), false, "Failed to set non-blocking mode");
342         /* recv timeout */
343         retvm_if(!set_recv_timeout(1), false, "Failed to set timeout");
344         /* TODO */
345         /*retvm_if(!set_reuse_addr(), false, "Failed to reuse address"); */
346
347         _D("Created[%d]", m_sock_fd);
348
349         m_path = path;
350
351         return true;
352 }
353
354 int socket::get_sock_type(void)
355 {
356         socklen_t opt_len;
357         int sock_type;
358         opt_len = sizeof(sock_type);
359
360         retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd);
361
362         if (getsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &sock_type, &opt_len) < 0) {
363            _ERRNO(errno, _E, "Failed to getsockopt from socket[%d]", m_sock_fd);
364            return false;
365         }
366
367         return sock_type;
368 }
369
370 bool socket::set_recv_timeout(int sec)
371 {
372         struct timeval timeout = {sec, 0};
373
374         retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd);
375
376         if (setsockopt(m_sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
377            _ERRNO(errno, _E, "Failed to setsockopt[%d]", m_sock_fd);
378            return false;
379         }
380
381         return true;
382 }
383
384 bool socket::set_sock_type(int type)
385 {
386         socklen_t opt_len;
387         opt_len = sizeof(type);
388
389         retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd);
390
391         if (setsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &type, opt_len) < 0) {
392            _ERRNO(errno, _E, "Failed to setsockopt[%d]", m_sock_fd);
393            return false;
394         }
395
396         return true;
397 }
398
399 bool socket::set_blocking_mode(bool blocking)
400 {
401         int flags;
402
403         flags = fcntl(m_sock_fd, F_GETFL);
404         retvm_if(flags == -1, false, "Failed to fcntl(F_GETFL)[%d]", m_sock_fd);
405
406         flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
407
408         flags = fcntl(m_sock_fd, F_SETFL, flags);
409         retvm_if(flags == -1, false, "Failed to fcntl(F_SETFL)[%d]", m_sock_fd);
410
411         return true;
412 }
413
414 bool socket::has_connected(void)
415 {
416         int so_error;
417         socklen_t len = sizeof(so_error);
418
419         if (getsockopt(m_sock_fd, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) {
420                 _E("Failed to call getsockopt[%d]", m_sock_fd);
421                 return false;
422         }
423
424         if (so_error) {
425                 _E("Failed to connect[%d]: %d", so_error);
426                 return false;
427         }
428
429         return true;
430 }
431
432 bool socket::set_buffer_size(int type, int size)
433 {
434         retv_if(m_sock_fd < 0, false);
435
436         int ret = 0;
437
438         ret = setsockopt(m_sock_fd, SOL_SOCKET, type, &size, sizeof(size));
439         retvm_if(ret < 0, false, "Failed to call setsocketopt()");
440
441         return true;
442 }
443
444 int socket::get_buffer_size(int type)
445 {
446         retv_if(m_sock_fd < 0, false);
447
448         int ret = 0;
449         int buf_size = 0;
450         socklen_t len;
451
452         ret = getsockopt(m_sock_fd, SOL_SOCKET, type, &buf_size, &len);
453         retvm_if(ret < 0, -EPERM, "Failed to call getsocketopt()");
454
455         return buf_size;
456 }
457
458 int socket::get_current_buffer_size(void)
459 {
460         retv_if(m_sock_fd < 0, false);
461
462         int queue_size = 0;
463         ioctl(m_sock_fd, TIOCOUTQ, &queue_size);
464
465         return queue_size;
466 }
467