sensord: redefine _ERRNO macro to use easily
[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
36 csocket::csocket(int sock_fd)
37 : m_sock_fd(-1)
38 , m_sock_type(SOCK_STREAM)
39 , m_send_flags(MSG_NOSIGNAL)
40 , m_recv_flags(MSG_NOSIGNAL)
41 {
42         m_sock_fd = sock_fd;
43         set_sock_type();
44         memset(&m_addr, 0, sizeof(m_addr));
45 }
46
47
48 csocket::csocket(const csocket &sock)
49 : m_sock_fd(-1)
50 , m_sock_type(SOCK_STREAM)
51 , m_send_flags(MSG_NOSIGNAL)
52 , m_recv_flags(MSG_NOSIGNAL)
53 {
54         if (this == &sock)
55                 return;
56
57         m_sock_fd = sock.m_sock_fd;
58         m_sock_type = sock.m_sock_type;
59         m_send_flags = sock.m_send_flags;
60         m_recv_flags = sock.m_recv_flags;
61
62         memcpy(&m_addr, &sock.m_addr, sizeof(sockaddr_un));
63 }
64
65 csocket::~csocket() { }
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         int addr_length = sizeof(m_addr);
136         int err = 0;
137
138         do {
139                 client_socket.m_sock_fd = ::accept(m_sock_fd, (sockaddr *)&m_addr, (socklen_t *)&addr_length);
140                 if (!client_socket.is_valid())
141                         err = errno;
142         } while (err == EINTR);
143
144         if (!client_socket.is_valid()) {
145                 _ERRNO(errno, _E, "Failed to accept for socket[%d]", m_sock_fd);
146                 return false;
147         }
148
149         return true;
150 }
151
152 ssize_t csocket::send_for_seqpacket(const void *buffer, size_t size) const
153 {
154         ssize_t err, len;
155
156         do {
157                 len = ::send(m_sock_fd, buffer, size, m_send_flags);
158                 err = len < 0 ? errno : 0;
159         } while (err == EINTR);
160
161         if (err) {
162                 _ERRNO(errno, _E, "Failed to send(%d, 0x%x, %d, 0x%x) = %d",
163                         m_sock_fd, buffer, size, m_send_flags, len);
164         }
165
166         return err == 0 ? len : -err;
167 }
168
169 ssize_t csocket::recv_for_seqpacket(void* buffer, size_t size) const
170 {
171         ssize_t err, len;
172
173         do {
174         len = ::recv(m_sock_fd, buffer, size, m_recv_flags);
175
176                 if (len > 0) {
177                         err = 0;
178                 } else if (len == 0) {
179                         _E("recv(%d, 0x%p , %d) = %d, because the peer performed shutdown!",
180                                 m_sock_fd, buffer, size, len);
181                         err = 1;
182                 } else {
183                         err = errno;
184                 }
185     } while (err == EINTR);
186
187         if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
188                 _ERRNO(err, _D, "Failed to recv(%d, 0x%x, %d, 0x%x) = %d",
189                         m_socket_fd, buffer, size, m_recv_flags, len);
190                 return 0;
191         }
192
193         if (err) {
194                 _ERRNO(err, _E, "Failed to recv(%d, 0x%x, %d, 0x%x) = %d",
195                         m_sock_fd, buffer, size, m_recv_flags, len);
196         }
197
198     return err == 0 ? len : -err;
199 }
200
201
202 ssize_t csocket::send_for_stream(const void *buffer, size_t size) const
203 {
204         ssize_t len;
205         ssize_t err = 0;
206         size_t total_sent_size = 0;
207
208         do {
209                 len = ::send(m_sock_fd, (const void *)((uint8_t *)buffer + total_sent_size), size - total_sent_size, m_send_flags);
210
211                 if (len >= 0) {
212                         total_sent_size += len;
213                         err = 0;
214                 } else {
215                         _ERRNO(errno, _E, "Failed to send(%d, 0x%p + %d, %d - %d) = %d for %s",
216                                 m_sock_fd, buffer, total_sent_size, size, total_sent_size,
217                                 len, get_client_name());
218
219                         if (errno != EINTR) {
220                                 err = errno;
221                                 break;
222                         }
223                 }
224         } while (total_sent_size < size);
225
226         return err == 0 ? total_sent_size : -err;
227 }
228
229 ssize_t csocket::recv_for_stream(void* buffer, size_t size) const
230 {
231         ssize_t len;
232         ssize_t err = 0;
233         size_t total_recv_size = 0;
234
235         do {
236                 len = ::recv(m_sock_fd, (void *)((uint8_t *)buffer + total_recv_size), size - total_recv_size, m_recv_flags);
237
238                 if (len > 0) {
239                         total_recv_size += len;
240                 } else if (len == 0) {
241                         _E("recv(%d, 0x%p + %d, %d - %d) = %d, because the peer of %s performed shutdown!",
242                                 m_sock_fd, buffer, total_recv_size, size, total_recv_size, len, get_client_name());
243                         err = 1;
244                         break;
245                 } else {
246                         _ERRNO(errno, _E, "Failed to recv(%d, 0x%p + %d, %d - %d) = %d for %s",
247                                 m_sock_fd, buffer, total_recv_size, size, total_recv_size,
248                                 len, get_client_name());
249
250                         if (errno != EINTR) {
251                                 err = errno;
252                                 break;
253                         }
254                 }
255         } while (total_recv_size < size);
256
257         return err == 0 ? total_recv_size : -err;
258 }
259
260
261 ssize_t csocket::send(const void *buffer, size_t size) const
262 {
263         if (!is_valid()) {
264                 _E("Socket(%d) is invalid", m_sock_fd);
265                 return -EINVAL;
266         }
267
268         if (m_sock_type == SOCK_STREAM)
269                 return send_for_stream(buffer, size);
270
271         return send_for_seqpacket(buffer, size);
272 }
273
274 ssize_t csocket::recv(void* buffer, size_t size) const
275 {
276         if (!is_valid()) {
277                 _E("Socket(%d) is invalid", m_sock_fd);
278                 return -EINVAL;
279         }
280
281         if (m_sock_type == SOCK_STREAM)
282                 return recv_for_stream(buffer, size);
283
284         return recv_for_seqpacket(buffer, size);
285 }
286
287 bool csocket::connect(const char *sock_path)
288 {
289         const int TIMEOUT = 5;
290         fd_set write_fds;
291         struct timeval tv;
292         int addr_len;
293         bool prev_blocking_mode;
294
295         if (!is_valid()) {
296                 _E("%s's socket is invalid", get_client_name());
297                 return false;
298         }
299
300         prev_blocking_mode = is_blocking_mode();
301
302         set_blocking_mode(false);
303
304         m_addr.sun_family = AF_UNIX;
305
306         strncpy(m_addr.sun_path, sock_path, strlen(sock_path));
307
308         addr_len = strlen(m_addr.sun_path) + sizeof(m_addr.sun_family);
309
310         if (::connect(m_sock_fd,(sockaddr *) &m_addr, addr_len) < 0) {
311                 _ERRNO(errno, _E, "Failed to connect sock_fd: %d for %s",
312                                 m_sock_fd, get_client_name());
313                 return false;
314         }
315
316         FD_ZERO(&write_fds);
317         FD_SET(m_sock_fd, &write_fds);
318         tv.tv_sec = TIMEOUT;
319         tv.tv_usec = 0;
320
321         int ret;
322
323         ret = select(m_sock_fd + 1, NULL, &write_fds, NULL, &tv);
324
325         if (ret == -1) {
326                 _ERRNO(errno, _E, "select error: sock_fd: %d\n for %s", m_sock_fd, get_client_name());
327                 close();
328                 return false;
329         } else if (!ret) {
330                 _ERRNO(errno, _E, "select timeout: %d seconds elapsed for %s", tv.tv_sec, get_client_name());
331                 close();
332                 return false;
333         }
334
335         if (!FD_ISSET(m_sock_fd, &write_fds)) {
336                 _ERRNO(errno, _E, "select failed for %s, nothing to write, m_sock_fd : %d", get_client_name(), m_sock_fd);
337                 close();
338                 return false;
339         }
340
341         int so_error;
342         socklen_t len = sizeof(so_error);
343
344         if (getsockopt(m_sock_fd, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) {
345                 _ERRNO(errno, _E, "getsockopt failed for %s, m_sock_fd : %d", get_client_name(), m_sock_fd);
346                 close();
347                 return false;
348         }
349
350         if (so_error) {
351                 _ERRNO(errno, _E, "SO_ERROR occurred for %s, m_sock_fd : %d, so_error : %d",
352                         get_client_name(), m_sock_fd, so_error);
353                 close();
354                 return false;
355         }
356
357         if (prev_blocking_mode)
358                 set_blocking_mode(true);
359
360         return true;
361 }
362
363 bool csocket::set_blocking_mode(bool blocking)
364 {
365         int flags;
366
367         if (!is_valid()) {
368                 _E("Socket(%d) is invalid", m_sock_fd);
369                 return false;
370         }
371
372         flags = fcntl(m_sock_fd, F_GETFL);
373
374         if (flags == -1) {
375                 _ERRNO(errno, _E, "fcntl(F_GETFL) failed for %s, m_sock_fd: %d", get_client_name(), m_sock_fd);
376                 return false;
377         }
378
379         flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
380
381         flags = fcntl(m_sock_fd, F_SETFL, flags);
382
383         if (flags == -1) {
384                 _ERRNO(errno, _E, "fcntl(F_SETFL) failed for %s, m_sock_fd: %d", get_client_name(), m_sock_fd);
385                 return false;
386         }
387
388         return true;
389 }
390
391
392 bool csocket::set_sock_type(void)
393 {
394         socklen_t opt_len;
395         int sock_type;
396
397         opt_len = sizeof(sock_type);
398
399         if (!is_valid()) {
400                 _E("Socket(%d) is invalid", m_sock_fd);
401                 return false;
402         }
403
404         if (getsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &sock_type, &opt_len) < 0) {
405            _ERRNO(errno, _E, "getsockopt(SOL_SOCKET, SO_TYPE) failed for %s, m_sock_fd: %d",
406                   get_client_name(), m_sock_fd);
407            return false;
408         }
409
410         m_sock_type = sock_type;
411         return true;
412 }
413
414 bool csocket::set_connection_mode(void)
415 {
416         struct timeval tv;
417         const int TIMEOUT = 5;
418
419         set_blocking_mode(true);
420
421         tv.tv_sec = TIMEOUT;
422         tv.tv_usec = 0;
423
424         if (!is_valid()) {
425                 _E("Socket(%d) is invalid", m_sock_fd);
426                 return false;
427         }
428
429         if(setsockopt(m_sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
430                 _ERRNO(errno, _E, "Set SO_RCVTIMEO failed for %s, m_sock_fd : %d", get_client_name(), m_sock_fd);
431                 close();
432                 return false;
433         }
434
435         m_send_flags = MSG_NOSIGNAL;
436         m_recv_flags = MSG_NOSIGNAL;
437
438         return true;
439 }
440
441 bool csocket::set_transfer_mode(void)
442 {
443         set_blocking_mode(false);
444
445         m_send_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
446         m_recv_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
447
448         return true;
449 }
450
451 bool csocket::is_blocking_mode(void)
452 {
453         int flags;
454
455         if (!is_valid()) {
456                 _E("Socket(%d) is invalid", m_sock_fd);
457                 return false;
458         }
459
460         flags = fcntl(m_sock_fd, F_GETFL);
461
462         if (flags == -1) {
463                 _ERRNO(errno, _E, "fcntl(F_GETFL) failed for %s, m_sock_fd: %d", get_client_name(), m_sock_fd);
464                 return false;
465         }
466
467         return !(flags & O_NONBLOCK);
468 }
469
470
471 bool csocket::is_valid(void) const
472 {
473         return (m_sock_fd >= 0);
474 }
475
476 int csocket::get_socket_fd(void) const
477 {
478         return m_sock_fd;
479 }
480
481 bool csocket::close(void)
482 {
483         if (m_sock_fd >= 0) {
484                 if (::close(m_sock_fd) < 0) {
485                         _ERRNO(errno, _E, "Failed to close socket[%d]", m_sock_fd);
486                         return false;
487                 }
488                 m_sock_fd = -1;
489         }
490
491         return true;
492 }