4 * Copyright (c) 2017 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.
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/ioctl.h>
28 #include <systemd/sd-daemon.h>
30 #include "sensor_log.h"
34 static bool set_close_on_exec(int fd)
36 if (::fcntl(fd, F_SETFL, FD_CLOEXEC) == -1)
42 static int create_systemd_socket(const std::string &path, int type)
47 listening = (type == SOCK_STREAM) ? 1 : -1;
50 retvm_if(n < 0, -EPERM, "Failed to listen fds from systemd");
52 for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) {
53 if (sd_is_socket_unix(fd, type, listening, path.c_str(), 0) > 0) {
54 set_close_on_exec(fd);
62 static int create_unix_socket(int type)
64 int sock_fd = ::socket(AF_UNIX, type, 0);
67 _ERRNO(errno, _E, "Failed to create socket");
71 set_close_on_exec(sock_fd);
74 if (::setsockopt(sock_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
75 _ERRNO(errno, _E, "Failed to create socket[%d]", sock_fd);
83 static bool select_fds(int fd, fd_set *read_fds, fd_set *write_fds, const int timeout)
92 err = ::select(fd + 1, read_fds, write_fds, NULL, &tv);
96 if (read_fds && FD_ISSET(fd, read_fds))
98 if (write_fds && FD_ISSET(fd, write_fds))
107 , m_mode(MSG_DONTWAIT | MSG_NOSIGNAL)
112 socket::socket(int sock_fd)
114 , m_mode(MSG_DONTWAIT | MSG_NOSIGNAL)
119 socket::socket(const socket &sock)
121 , m_mode(MSG_DONTWAIT | MSG_NOSIGNAL)
127 m_sock_fd = sock.m_sock_fd;
128 m_mode = sock.m_mode;
129 m_listening.store(sock.m_listening);
137 bool socket::connect(void)
139 const int TIMEOUT = 3;
143 FD_SET(m_sock_fd, &write_fds);
145 retvm_if(m_path.size() >= sizeof(sockaddr_un::sun_path), false,
146 "Failed to create socket[%s]", m_path.c_str());
148 addr.sun_family = AF_UNIX;
149 strncpy(addr.sun_path, m_path.c_str(), sizeof(sockaddr_un::sun_path));
150 addr.sun_path[m_path.size()] = '\0';
152 if (::connect(m_sock_fd,
153 reinterpret_cast<struct sockaddr *>(&addr),
154 sizeof(struct sockaddr_un)) < 0) {
155 _ERRNO(errno, _E, "Failed to connect() for socket[%d]", m_sock_fd);
160 if (!select_fds(m_sock_fd, NULL, &write_fds, TIMEOUT)) {
161 _E("Failed to select for socket[%d]", m_sock_fd);
166 if (!has_connected()) {
171 _D("Connected[%d]", m_sock_fd);
176 bool socket::bind(void)
181 retvm_if(m_path.size() >= sizeof(sockaddr_un::sun_path), false,
182 "Failed to create socket[%s]", m_path.c_str());
183 retv_if(m_listening.load(), true);
185 if (!access(m_path.c_str(), F_OK))
186 unlink(m_path.c_str());
188 addr.sun_family = AF_UNIX;
189 ::strncpy(addr.sun_path, m_path.c_str(), sizeof(sockaddr_un::sun_path));
190 addr.sun_path[m_path.size()] = '\0';
192 if (::bind(m_sock_fd,
193 reinterpret_cast<struct sockaddr *>(&addr),
194 sizeof(struct sockaddr_un)) < 0) {
195 _ERRNO(errno, _E, "Failed to bind for socket[%d]", m_sock_fd);
200 /* TODO: Is this really necessary? */
201 file_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
202 if (chmod(m_path.c_str(), file_mode) < 0) {
203 _ERRNO(errno, _E, "Failed to create socket[%d]", m_sock_fd);
208 _D("Bound to path[%d, %s]", m_sock_fd, m_path.c_str());
213 bool socket::listen(const int max_connections)
215 retv_if(m_listening.load(), true);
217 if (::listen(m_sock_fd, max_connections) < 0) {
218 _ERRNO(errno, _E, "Failed to listen() for socket[%d]", m_sock_fd);
223 m_listening.store(true);
225 _D("Listened[%d]", m_sock_fd);
230 bool socket::accept(socket &client_sock)
235 FD_SET(m_sock_fd, &read_fds);
237 fd = ::accept(m_sock_fd, NULL, NULL);
240 _ERRNO(errno, _E, "Failed to accept[%d]", m_sock_fd);
244 set_close_on_exec(fd);
245 client_sock.set_fd(fd);
246 /* TODO : socket type should be adjusted here */
248 _D("Accepted[%d, %d]", m_sock_fd, fd);
253 bool socket::close(void)
255 retv_if(m_sock_fd < 0, false);
257 if (::close(m_sock_fd) < 0)
260 _D("Closed[%d]", m_sock_fd);
263 m_listening.store(false);
268 int socket::get_fd(void) const
273 void socket::set_fd(int sock_fd)
278 int socket::get_mode(void) const
283 bool socket::set_mode(int mode)
285 /* TODO : implement send/recv message mode */
289 bool socket::create(const std::string &path)
294 ssize_t socket::send(const void *buffer, size_t size, bool select) const
297 const int TIMEOUT = 1;
300 FD_SET(m_sock_fd, &write_fds);
302 if (!select_fds(m_sock_fd, NULL, &write_fds, TIMEOUT)) {
303 _E("Failed to send message(timeout)");
308 return on_send(buffer, size);
311 ssize_t socket::recv(void* buffer, size_t size, bool select) const
314 const int TIMEOUT = 1;
317 FD_SET(m_sock_fd, &read_fds);
319 if (!select_fds(m_sock_fd, &read_fds, NULL, TIMEOUT)) {
320 _E("Failed to receive message(timeout)");
325 return on_recv(buffer, size);
328 bool socket::create_by_type(const std::string &path, int type)
330 m_sock_fd = ::create_systemd_socket(path, type);
332 _D("Creating the UDS instead of systemd socket..");
333 m_sock_fd = create_unix_socket(type);
335 m_listening.store(true);
338 retvm_if((m_sock_fd < 0), false, "Failed to create socket");
340 /* non-blocking mode */
341 retvm_if(!set_blocking_mode(false), false, "Failed to set non-blocking mode");
343 retvm_if(!set_recv_timeout(1), false, "Failed to set timeout");
345 /*retvm_if(!set_reuse_addr(), false, "Failed to reuse address"); */
347 _D("Created[%d]", m_sock_fd);
354 int socket::get_sock_type(void)
358 opt_len = sizeof(sock_type);
360 retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd);
362 if (getsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &sock_type, &opt_len) < 0) {
363 _ERRNO(errno, _E, "Failed to getsockopt from socket[%d]", m_sock_fd);
370 bool socket::set_recv_timeout(int sec)
372 struct timeval timeout = {sec, 0};
374 retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd);
376 if (setsockopt(m_sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
377 _ERRNO(errno, _E, "Failed to setsockopt[%d]", m_sock_fd);
384 bool socket::set_sock_type(int type)
387 opt_len = sizeof(type);
389 retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd);
391 if (setsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &type, opt_len) < 0) {
392 _ERRNO(errno, _E, "Failed to setsockopt[%d]", m_sock_fd);
399 bool socket::set_blocking_mode(bool blocking)
403 flags = fcntl(m_sock_fd, F_GETFL);
404 retvm_if(flags == -1, false, "Failed to fcntl(F_GETFL)[%d]", m_sock_fd);
406 flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
408 flags = fcntl(m_sock_fd, F_SETFL, flags);
409 retvm_if(flags == -1, false, "Failed to fcntl(F_SETFL)[%d]", m_sock_fd);
414 bool socket::has_connected(void)
417 socklen_t len = sizeof(so_error);
419 if (getsockopt(m_sock_fd, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) {
420 _E("Failed to call getsockopt[%d]", m_sock_fd);
425 _E("Failed to connect[%d]: %d", so_error);
432 bool socket::set_buffer_size(int type, int size)
434 retv_if(m_sock_fd < 0, false);
438 ret = setsockopt(m_sock_fd, SOL_SOCKET, type, &size, sizeof(size));
439 retvm_if(ret < 0, false, "Failed to call setsocketopt()");
444 int socket::get_buffer_size(int type)
446 retv_if(m_sock_fd < 0, false);
452 ret = getsockopt(m_sock_fd, SOL_SOCKET, type, &buf_size, &len);
453 retvm_if(ret < 0, -EPERM, "Failed to call getsocketopt()");
458 int socket::get_current_buffer_size(void)
460 retv_if(m_sock_fd < 0, false);
463 ioctl(m_sock_fd, TIOCOUTQ, &queue_size);