sensord: terminate sensor daemon safely
[platform/core/system/sensord.git] / src / shared / csocket.cpp
1 /*
2  * sensord
3  *
4  * Copyright (c) 2013 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 <sensor_log.h>
21 #include <csocket.h>
22 #include <attr/xattr.h>
23 #include <sys/stat.h>
24 #include <stdint.h>
25
26 csocket::csocket()
27 : m_sock_fd(-1)
28 , m_sock_type(SOCK_STREAM)
29 , m_send_flags(MSG_NOSIGNAL)
30 , m_recv_flags(MSG_NOSIGNAL)
31 {
32         memset(&m_addr, 0, sizeof(m_addr));
33 }
34
35 csocket::csocket(int sock_fd)
36 : m_sock_fd(-1)
37 , m_sock_type(SOCK_STREAM)
38 , m_send_flags(MSG_NOSIGNAL)
39 , m_recv_flags(MSG_NOSIGNAL)
40 {
41         m_sock_fd = sock_fd;
42         set_sock_type();
43         memset(&m_addr, 0, sizeof(m_addr));
44 }
45
46 csocket::csocket(const csocket &sock)
47 : m_sock_fd(-1)
48 , m_sock_type(SOCK_STREAM)
49 , m_send_flags(MSG_NOSIGNAL)
50 , m_recv_flags(MSG_NOSIGNAL)
51 {
52         if (this == &sock)
53                 return;
54
55         m_sock_fd = sock.m_sock_fd;
56         m_sock_type = sock.m_sock_type;
57         m_send_flags = sock.m_send_flags;
58         m_recv_flags = sock.m_recv_flags;
59
60         memcpy(&m_addr, &sock.m_addr, sizeof(sockaddr_un));
61 }
62
63 csocket::~csocket() { }
64
65 bool csocket::create(int sock_type)
66 {
67         m_sock_fd = socket(AF_UNIX, sock_type, 0);
68
69         if (!is_valid()) {
70                 _ERRNO(errno, _E, "Failed to create socket for %s", get_client_name());
71                 return false;
72         }
73
74         m_sock_type = sock_type;
75
76         return true;
77 }
78
79 bool csocket::bind(const char *sock_path)
80 {
81         int length;
82         mode_t socket_mode;
83
84         if (!is_valid()) {
85                 _E("%s's socket is invalid", get_client_name());
86                 return false;
87         }
88
89         if (!access(sock_path, F_OK)) {
90                 unlink(sock_path);
91         }
92
93         m_addr.sun_family = AF_UNIX;
94
95         strncpy(m_addr.sun_path, sock_path, strlen(sock_path));
96
97         length = strlen(m_addr.sun_path) + sizeof(m_addr.sun_family);
98
99         if (::bind(m_sock_fd, (struct sockaddr *)&m_addr, length) < 0) {
100                 _ERRNO(errno, _E, "Failed to bind for socket[%d]", m_sock_fd);
101                 close();
102                 return false;
103         }
104
105         socket_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
106         if (chmod(sock_path, socket_mode) < 0) {
107                 _ERRNO(errno, _E, "Failed to chmod for socket[%d]", m_sock_fd);
108                 close();
109                 return false;
110         }
111
112         return true;
113 }
114
115 bool csocket::listen(const int max_connections)
116 {
117         if (!is_valid()) {
118                 _E("Socket(%d) is invalid", m_sock_fd);
119                 return false;
120         }
121
122         if (::listen(m_sock_fd, max_connections) < 0) {
123                 _ERRNO(errno, _E, "Failed to listen for socket[%d]", m_sock_fd);
124                 close();
125                 return false;
126         }
127
128         return true;
129 }
130
131 bool csocket::accept(csocket& client_socket) const
132 {
133         const int TIMEOUT = 1;
134         struct timeval tv;
135         int addr_length = sizeof(m_addr);
136         int err = 0;
137
138         fd_set read_fds;
139
140         while (true) {
141                 FD_ZERO(&read_fds);
142                 FD_SET(m_sock_fd, &read_fds);
143
144                 tv.tv_sec = TIMEOUT;
145                 tv.tv_usec = 0;
146
147                 err = ::select(m_sock_fd + 1, &read_fds, NULL, NULL, &tv);
148                 if (err == -1) {
149                         _ERRNO(errno, _E, "Failed to select(), m_sock_fd : %d", m_sock_fd);
150                         return false;
151                 }
152
153                 if (!is_valid()) {
154                         _E("socket is closed, m_sock_fd : %d", m_sock_fd);
155                         return false;
156                 }
157
158                 /* timeout */
159                 if (!err)
160                         continue;
161
162                 if (FD_ISSET(m_sock_fd, &read_fds))
163                         break;
164
165                 _ERRNO(errno, _E, "Failed to select(), msock_fd : %d", m_sock_fd);
166         }
167
168         if (!is_valid()) {
169                 _E("socket is closed, m_sock_fd : %d", m_sock_fd);
170                 return false;
171         }
172
173         do {
174                 client_socket.m_sock_fd = ::accept(m_sock_fd, (sockaddr *)&m_addr, (socklen_t *)&addr_length);
175                 if (!client_socket.is_valid())
176                         err = errno;
177         } while (err == EINTR);
178
179         if (!client_socket.is_valid()) {
180                 _ERRNO(errno, _E, "Failed to accept for socket[%d]", m_sock_fd);
181                 return false;
182         }
183
184         return true;
185 }
186
187 ssize_t csocket::send_for_seqpacket(const void *buffer, size_t size) const
188 {
189         ssize_t err, len;
190
191         do {
192                 len = ::send(m_sock_fd, buffer, size, m_send_flags);
193                 err = len < 0 ? errno : 0;
194         } while (err == EINTR);
195
196         if (err) {
197                 _ERRNO(errno, _E, "Failed to send(%d, %#x, %d, %#x) = %d",
198                         m_sock_fd, buffer, size, m_send_flags, len);
199         }
200
201         return err == 0 ? len : -err;
202 }
203
204 ssize_t csocket::recv_for_seqpacket(void* buffer, size_t size) const
205 {
206         ssize_t err, len;
207
208         do {
209                 len = ::recv(m_sock_fd, buffer, size, m_recv_flags);
210
211                 if (len > 0) {
212                         err = 0;
213                 } else if (len == 0) {
214                         _E("recv(%d, %#p , %d) = %d, because the peer performed shutdown!",
215                                 m_sock_fd, buffer, size, len);
216                         err = 1;
217                 } else {
218                         err = errno;
219                 }
220         } while (err == EINTR);
221
222         if ((err == EAGAIN) || (err == EWOULDBLOCK))
223                 return 0;
224
225         if (err) {
226                 _ERRNO(err, _E, "Failed to recv(%d, %#x, %d, %#x) = %d",
227                         m_sock_fd, buffer, size, m_recv_flags, len);
228         }
229
230         return err == 0 ? len : -err;
231 }
232
233 ssize_t csocket::send_for_stream(const void *buffer, size_t size) const
234 {
235         ssize_t len;
236         ssize_t err = 0;
237         size_t total_sent_size = 0;
238
239         do {
240                 len = ::send(m_sock_fd, (const void *)((uint8_t *)buffer + total_sent_size), size - total_sent_size, m_send_flags);
241
242                 if (len >= 0) {
243                         total_sent_size += len;
244                         err = 0;
245                 } else {
246                         _ERRNO(errno, _E, "Failed to send(%d, %#p + %d, %d - %d) = %d for %s",
247                                 m_sock_fd, buffer, total_sent_size, size, total_sent_size,
248                                 len, get_client_name());
249
250                         /*
251                         * If socket is not available to use it temporarily,
252                         * EAGAIN(EWOULDBLOCK) is returned by ::send().
253                         * so in order to prevent that data are omitted, retry to send it
254                         */
255                         if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
256                                 usleep(1000);
257                                 continue;
258                         }
259
260                         if (errno != EINTR) {
261                                 err = errno;
262                                 break;
263                         }
264                 }
265         } while (total_sent_size < size);
266
267         return err == 0 ? total_sent_size : -err;
268 }
269
270 ssize_t csocket::recv_for_stream(void* buffer, size_t size) const
271 {
272         ssize_t len;
273         ssize_t err = 0;
274         size_t total_recv_size = 0;
275
276         do {
277                 len = ::recv(m_sock_fd, (void *)((uint8_t *)buffer + total_recv_size), size - total_recv_size, m_recv_flags);
278
279                 if (len > 0) {
280                         total_recv_size += len;
281                 } else if (len == 0) {
282                         _E("recv(%d, %#p + %d, %d - %d) = %d, because the peer of %s performed shutdown!",
283                                 m_sock_fd, buffer, total_recv_size, size, total_recv_size, len, get_client_name());
284                         err = 1;
285                         break;
286                 } else {
287                         _ERRNO(errno, _E, "Failed to recv(%d, %#p + %d, %d - %d) = %d for %s",
288                                 m_sock_fd, buffer, total_recv_size, size, total_recv_size,
289                                 len, get_client_name());
290
291                         /*
292                         * If socket is not available to use during for some time,
293                         * EAGAIN(EWOULDBLOCK) is returned by ::recv().
294                         * so in order to prevent that data are omitted, retry to receive it
295                         */
296                         if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
297                                 usleep(1000);
298                                 continue;
299                         }
300
301                         if (errno != EINTR) {
302                                 err = errno;
303                                 break;
304                         }
305                 }
306         } while (total_recv_size < size);
307
308         return err == 0 ? total_recv_size : -err;
309 }
310
311 ssize_t csocket::send(const void *buffer, size_t size) const
312 {
313         if (!is_valid()) {
314                 _E("Socket(%d) is invalid", m_sock_fd);
315                 return -EINVAL;
316         }
317
318         if (m_sock_type == SOCK_STREAM)
319                 return send_for_stream(buffer, size);
320
321         return send_for_seqpacket(buffer, size);
322 }
323
324 ssize_t csocket::recv(void* buffer, size_t size) const
325 {
326         if (!is_valid()) {
327                 _E("Socket(%d) is invalid", m_sock_fd);
328                 return -EINVAL;
329         }
330
331         if (m_sock_type == SOCK_STREAM)
332                 return recv_for_stream(buffer, size);
333
334         return recv_for_seqpacket(buffer, size);
335 }
336
337 bool csocket::connect(const char *sock_path)
338 {
339         const int TIMEOUT = 5;
340         fd_set write_fds;
341         struct timeval tv;
342         int addr_len;
343         bool prev_blocking_mode;
344
345         if (!is_valid()) {
346                 _E("%s's socket is invalid", get_client_name());
347                 return false;
348         }
349
350         prev_blocking_mode = is_blocking_mode();
351
352         set_blocking_mode(false);
353
354         m_addr.sun_family = AF_UNIX;
355
356         strncpy(m_addr.sun_path, sock_path, strlen(sock_path));
357
358         addr_len = strlen(m_addr.sun_path) + sizeof(m_addr.sun_family);
359
360         if (::connect(m_sock_fd, (sockaddr *) &m_addr, addr_len) < 0) {
361                 _ERRNO(errno, _E, "Failed to connect sock_fd: %d for %s",
362                                 m_sock_fd, get_client_name());
363                 return false;
364         }
365
366         FD_ZERO(&write_fds);
367         FD_SET(m_sock_fd, &write_fds);
368         tv.tv_sec = TIMEOUT;
369         tv.tv_usec = 0;
370
371         int ret;
372
373         ret = select(m_sock_fd + 1, NULL, &write_fds, NULL, &tv);
374
375         if (ret == -1) {
376                 _ERRNO(errno, _E, "select error: sock_fd: %d\n for %s", m_sock_fd, get_client_name());
377                 close();
378                 return false;
379         } else if (!ret) {
380                 _ERRNO(errno, _E, "select timeout: %d seconds elapsed for %s", tv.tv_sec, get_client_name());
381                 close();
382                 return false;
383         }
384
385         if (!FD_ISSET(m_sock_fd, &write_fds)) {
386                 _ERRNO(errno, _E, "select failed for %s, nothing to write, m_sock_fd : %d", get_client_name(), m_sock_fd);
387                 close();
388                 return false;
389         }
390
391         int so_error;
392         socklen_t len = sizeof(so_error);
393
394         if (getsockopt(m_sock_fd, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) {
395                 _ERRNO(errno, _E, "getsockopt failed for %s, m_sock_fd : %d", get_client_name(), m_sock_fd);
396                 close();
397                 return false;
398         }
399
400         if (so_error) {
401                 _ERRNO(errno, _E, "SO_ERROR occurred for %s, m_sock_fd : %d, so_error : %d",
402                         get_client_name(), m_sock_fd, so_error);
403                 close();
404                 return false;
405         }
406
407         if (prev_blocking_mode)
408                 set_blocking_mode(true);
409
410         return true;
411 }
412
413 bool csocket::set_blocking_mode(bool blocking)
414 {
415         int flags;
416
417         if (!is_valid()) {
418                 _E("Socket(%d) is invalid", m_sock_fd);
419                 return false;
420         }
421
422         flags = fcntl(m_sock_fd, F_GETFL);
423
424         if (flags == -1) {
425                 _ERRNO(errno, _E, "fcntl(F_GETFL) failed for %s, m_sock_fd: %d", get_client_name(), m_sock_fd);
426                 return false;
427         }
428
429         flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
430
431         flags = fcntl(m_sock_fd, F_SETFL, flags);
432
433         if (flags == -1) {
434                 _ERRNO(errno, _E, "fcntl(F_SETFL) failed for %s, m_sock_fd: %d", get_client_name(), m_sock_fd);
435                 return false;
436         }
437
438         return true;
439 }
440
441 bool csocket::set_sock_type(void)
442 {
443         socklen_t opt_len;
444         int sock_type;
445
446         opt_len = sizeof(sock_type);
447
448         if (!is_valid()) {
449                 _E("Socket(%d) is invalid", m_sock_fd);
450                 return false;
451         }
452
453         if (getsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &sock_type, &opt_len) < 0) {
454            _ERRNO(errno, _E, "getsockopt(SOL_SOCKET, SO_TYPE) failed for %s, m_sock_fd: %d",
455                   get_client_name(), m_sock_fd);
456            return false;
457         }
458
459         m_sock_type = sock_type;
460         return true;
461 }
462
463 bool csocket::set_connection_mode(void)
464 {
465         struct timeval tv;
466         const int TIMEOUT = 5;
467
468         set_blocking_mode(true);
469
470         tv.tv_sec = TIMEOUT;
471         tv.tv_usec = 0;
472
473         if (!is_valid()) {
474                 _E("Socket(%d) is invalid", m_sock_fd);
475                 return false;
476         }
477
478         if (setsockopt(m_sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
479                 _ERRNO(errno, _E, "Set SO_RCVTIMEO failed for %s, m_sock_fd : %d", get_client_name(), m_sock_fd);
480                 close();
481                 return false;
482         }
483
484         m_send_flags = MSG_NOSIGNAL;
485         m_recv_flags = MSG_NOSIGNAL;
486
487         return true;
488 }
489
490 bool csocket::set_transfer_mode(void)
491 {
492         set_blocking_mode(false);
493
494         m_send_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
495         m_recv_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
496
497         return true;
498 }
499
500 bool csocket::is_blocking_mode(void)
501 {
502         int flags;
503
504         if (!is_valid()) {
505                 _E("Socket(%d) is invalid", m_sock_fd);
506                 return false;
507         }
508
509         flags = fcntl(m_sock_fd, F_GETFL);
510
511         if (flags == -1) {
512                 _ERRNO(errno, _E, "fcntl(F_GETFL) failed for %s, m_sock_fd: %d", get_client_name(), m_sock_fd);
513                 return false;
514         }
515
516         return !(flags & O_NONBLOCK);
517 }
518
519 bool csocket::is_valid(void) const
520 {
521         return (m_sock_fd >= 0);
522 }
523
524 int csocket::get_socket_fd(void) const
525 {
526         return m_sock_fd;
527 }
528
529 bool csocket::close(void)
530 {
531         if (m_sock_fd >= 0) {
532                 if (::close(m_sock_fd) < 0) {
533                         _ERRNO(errno, _E, "Failed to close socket[%d]", m_sock_fd);
534                         return false;
535                 }
536                 m_sock_fd = -1;
537         }
538
539         return true;
540 }