4 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <attr/xattr.h>
27 , m_sock_type(SOCK_STREAM)
28 , m_send_flags(MSG_NOSIGNAL)
29 , m_recv_flags(MSG_NOSIGNAL)
31 memset(&m_addr, 0, sizeof(m_addr));
35 csocket::csocket(int sock_fd)
37 , m_sock_type(SOCK_STREAM)
38 , m_send_flags(MSG_NOSIGNAL)
39 , m_recv_flags(MSG_NOSIGNAL)
43 memset(&m_addr, 0, sizeof(m_addr));
47 csocket::csocket(const csocket &sock)
49 , m_sock_type(SOCK_STREAM)
50 , m_send_flags(MSG_NOSIGNAL)
51 , m_recv_flags(MSG_NOSIGNAL)
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;
61 memcpy(&m_addr, &sock.m_addr, sizeof(sockaddr_un));
64 csocket::~csocket() { }
66 bool csocket::create(int sock_type)
68 m_sock_fd = socket(AF_UNIX, sock_type, 0);
71 _E("Failed to create socket for %s, errno : %d , errstr : %s ",
72 get_client_name(), errno, strerror(errno));
76 m_sock_type = sock_type;
81 bool csocket::bind (const char *sock_path)
87 _E("%s's socket is invalid", get_client_name());
91 if((fsetxattr(m_sock_fd, "security.SMACK64IPOUT", "@", 2, 0)) < 0) {
92 if(errno != EOPNOTSUPP) {
94 _E("security.SMACK64IPOUT error = [%d][%s]\n", errno, strerror(errno) );
99 if((fsetxattr(m_sock_fd, "security.SMACK64IPIN", "*", 2, 0)) < 0) {
100 if(errno != EOPNOTSUPP) {
102 _E("security.SMACK64IPIN error = [%d][%s]\n", errno, strerror(errno) );
107 if (!access(sock_path, F_OK)) {
111 m_addr.sun_family = AF_UNIX;
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';
116 length = strlen(m_addr.sun_path) + sizeof(m_addr.sun_family);
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));
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));
134 bool csocket::listen(const int max_connections)
137 _E("Socket(%d) is invalid", m_sock_fd);
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));
150 bool csocket::accept(csocket& client_socket) const
152 int addr_length = sizeof(m_addr);
156 client_socket.m_sock_fd = ::accept(m_sock_fd, (sockaddr *)&m_addr, (socklen_t *)&addr_length);
157 if (!client_socket.is_valid()) {
159 ::close(client_socket.m_sock_fd);
161 } while (err == EINTR);
163 if (!client_socket.is_valid()) {
164 _E("Accept failed for socket(%d), errno : %d , errstr : %s", m_sock_fd, errno, strerror(errno));
171 ssize_t csocket::send_for_seqpacket(const void *buffer, size_t size) const
176 len = ::send(m_sock_fd, buffer, size, m_send_flags);
177 err = len < 0 ? errno : 0;
178 } while (err == EINTR);
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);
185 return err == 0 ? len : -err;
188 ssize_t csocket::recv_for_seqpacket(void* buffer, size_t size) const
193 len = ::recv(m_sock_fd, buffer, size, m_recv_flags);
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);
204 } while (err == EINTR);
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);
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);
217 return err == 0 ? len : -err;
221 ssize_t csocket::send_for_stream(const void *buffer, size_t size) const
225 size_t total_sent_size = 0;
228 len = ::send(m_sock_fd, (const void *)((uint8_t *)buffer + total_sent_size), size - total_sent_size, m_send_flags);
231 total_sent_size += len;
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());
238 if (errno != EINTR) {
243 } while (total_sent_size < size);
245 return err == 0 ? total_sent_size : -err;
248 ssize_t csocket::recv_for_stream(void* buffer, size_t size) const
252 size_t total_recv_size = 0;
255 len = ::recv(m_sock_fd, (void *)((uint8_t *)buffer + total_recv_size), size - total_recv_size, m_recv_flags);
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());
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());
269 if (errno != EINTR) {
274 } while (total_recv_size < size);
276 return err == 0 ? total_recv_size : -err;
280 ssize_t csocket::send(const void *buffer, size_t size) const
282 if (m_sock_type == SOCK_STREAM)
283 return send_for_stream(buffer, size);
285 return send_for_seqpacket(buffer, size);
288 ssize_t csocket::recv(void* buffer, size_t size) const
290 if (m_sock_type == SOCK_STREAM)
291 return recv_for_stream(buffer, size);
293 return recv_for_seqpacket(buffer, size);
296 bool csocket::connect(const char *sock_path)
298 const int TIMEOUT = 5;
302 bool prev_blocking_mode;
305 _E("%s's socket is invalid", get_client_name());
309 prev_blocking_mode = is_blocking_mode();
311 set_blocking_mode(false);
313 m_addr.sun_family = AF_UNIX;
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';
318 addr_len = strlen(m_addr.sun_path) + sizeof(m_addr.sun_family);
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());
326 FD_SET(m_sock_fd, &write_fds);
332 ret = select(m_sock_fd + 1, NULL, &write_fds, NULL, &tv);
335 _E("select error: %s sock_fd: %d\n for %s", strerror(errno), m_sock_fd, get_client_name());
339 _E("select timeout: %d seconds elapsed for %s", tv.tv_sec, get_client_name());
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);
351 socklen_t len = sizeof(so_error);
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));
361 _E("SO_ERROR occurred for %s, m_sock_fd : %d, so_error : %d",
362 get_client_name(), m_sock_fd, so_error);
367 if (prev_blocking_mode)
368 set_blocking_mode(true);
373 bool csocket::set_blocking_mode(bool blocking)
377 flags = fcntl(m_sock_fd, F_GETFL);
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));
384 flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
386 flags = fcntl(m_sock_fd, F_SETFL, flags);
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));
397 bool csocket::set_sock_type(void)
402 opt_len = sizeof(sock_type);
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));
409 m_sock_type = sock_type;
413 bool csocket::set_connection_mode(void)
416 const int TIMEOUT = 5;
418 set_blocking_mode(true);
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));
430 m_send_flags = MSG_NOSIGNAL;
431 m_recv_flags = MSG_NOSIGNAL;
436 bool csocket::set_transfer_mode(void)
438 set_blocking_mode(false);
441 m_send_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
442 m_recv_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
447 bool csocket::is_blocking_mode(void)
451 flags = fcntl(m_sock_fd, F_GETFL);
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));
458 return !(flags & O_NONBLOCK);
462 bool csocket::is_valid(void) const
464 return (m_sock_fd >= 0);
467 int csocket::get_socket_fd(void) const
472 bool csocket::close(void)
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));