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