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