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