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"
32 #define SOCK_TIMEOUT 3
36 static bool set_close_on_exec(int fd)
38 if (::fcntl(fd, F_SETFL, FD_CLOEXEC) == -1)
44 static int create_systemd_socket(const std::string &path, int type)
49 listening = (type == SOCK_STREAM) ? 1 : -1;
52 retvm_if(n < 0, -EPERM, "Failed to listen fds from systemd");
54 for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) {
55 if (sd_is_socket_unix(fd, type, listening, path.c_str(), 0) > 0) {
56 set_close_on_exec(fd);
64 static int create_unix_socket(int type)
66 int sock_fd = ::socket(AF_UNIX, type, 0);
69 _ERRNO(errno, _E, "Failed to create socket");
73 set_close_on_exec(sock_fd);
76 if (::setsockopt(sock_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
77 _ERRNO(errno, _E, "Failed to create socket[%d]", sock_fd);
85 static bool select_fds(int fd, fd_set *read_fds, fd_set *write_fds, const int timeout)
94 err = ::select(fd + 1, read_fds, write_fds, NULL, &tv);
98 if (read_fds && FD_ISSET(fd, read_fds))
100 if (write_fds && FD_ISSET(fd, write_fds))
109 , m_mode(MSG_DONTWAIT | MSG_NOSIGNAL)
114 socket::socket(int sock_fd)
116 , m_mode(MSG_DONTWAIT | MSG_NOSIGNAL)
121 socket::socket(const socket &sock)
123 , m_mode(MSG_DONTWAIT | MSG_NOSIGNAL)
129 m_sock_fd = sock.m_sock_fd;
130 m_mode = sock.m_mode;
131 m_listening.store(sock.m_listening);
139 bool socket::connect(void)
144 FD_SET(m_sock_fd, &write_fds);
146 retvm_if(m_path.size() >= sizeof(sockaddr_un::sun_path), false,
147 "Failed to create socket[%s]", m_path.c_str());
149 addr.sun_family = AF_UNIX;
150 strncpy(addr.sun_path, m_path.c_str(), sizeof(sockaddr_un::sun_path));
151 addr.sun_path[m_path.size()] = '\0';
153 if (::connect(m_sock_fd,
154 reinterpret_cast<struct sockaddr *>(&addr),
155 sizeof(struct sockaddr_un)) < 0) {
156 _ERRNO(errno, _E, "Failed to connect() for socket[%d]", m_sock_fd);
161 if (!select_fds(m_sock_fd, NULL, &write_fds, SOCK_TIMEOUT)) {
162 _E("Failed to select for socket[%d]", m_sock_fd);
167 if (!has_connected()) {
172 _D("Connected[%d]", m_sock_fd);
177 bool socket::bind(void)
182 retvm_if(m_path.size() >= sizeof(sockaddr_un::sun_path), false,
183 "Failed to create socket[%s]", m_path.c_str());
184 retv_if(m_listening.load(), true);
186 if (!access(m_path.c_str(), F_OK))
187 unlink(m_path.c_str());
189 addr.sun_family = AF_UNIX;
190 ::strncpy(addr.sun_path, m_path.c_str(), sizeof(sockaddr_un::sun_path));
191 addr.sun_path[m_path.size()] = '\0';
193 if (::bind(m_sock_fd,
194 reinterpret_cast<struct sockaddr *>(&addr),
195 sizeof(struct sockaddr_un)) < 0) {
196 _ERRNO(errno, _E, "Failed to bind for socket[%d]", m_sock_fd);
201 /* TODO: Is this really necessary? */
202 file_mode = (S_IRWXU | S_IRWXG | S_IRWXO);
203 if (chmod(m_path.c_str(), file_mode) < 0) {
204 _ERRNO(errno, _E, "Failed to create socket[%d]", m_sock_fd);
209 _D("Bound to path[%d, %s]", m_sock_fd, m_path.c_str());
214 bool socket::listen(const int max_connections)
216 retv_if(m_listening.load(), true);
218 if (::listen(m_sock_fd, max_connections) < 0) {
219 _ERRNO(errno, _E, "Failed to listen() for socket[%d]", m_sock_fd);
224 m_listening.store(true);
226 _D("Listened[%d]", m_sock_fd);
231 bool socket::accept(socket &client_sock)
236 FD_SET(m_sock_fd, &read_fds);
238 fd = ::accept(m_sock_fd, NULL, NULL);
241 _ERRNO(errno, _E, "Failed to accept[%d]", m_sock_fd);
245 set_close_on_exec(fd);
246 client_sock.set_fd(fd);
247 /* TODO : socket type should be adjusted here */
249 _D("Accepted[%d, %d]", m_sock_fd, fd);
254 bool socket::close(void)
256 retv_if(m_sock_fd < 0, false);
258 if (::close(m_sock_fd) < 0)
261 _D("Closed[%d]", m_sock_fd);
264 m_listening.store(false);
269 int socket::get_fd(void) const
274 void socket::set_fd(int sock_fd)
279 int socket::get_mode(void) const
284 bool socket::set_mode(int mode)
286 /* TODO : implement send/recv message mode */
290 bool socket::create(const std::string &path)
295 ssize_t socket::send(const void *buffer, size_t size, bool select) const
300 FD_SET(m_sock_fd, &write_fds);
302 if (!select_fds(m_sock_fd, NULL, &write_fds, SOCK_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
316 FD_SET(m_sock_fd, &read_fds);
318 if (!select_fds(m_sock_fd, &read_fds, NULL, SOCK_TIMEOUT)) {
319 _E("Failed to receive message(timeout)");
324 return on_recv(buffer, size);
327 bool socket::create_by_type(const std::string &path, int type)
329 m_sock_fd = ::create_systemd_socket(path, type);
331 _D("Creating the UDS instead of systemd socket..");
332 m_sock_fd = create_unix_socket(type);
334 m_listening.store(true);
337 retvm_if((m_sock_fd < 0), false, "Failed to create socket");
339 /* non-blocking mode */
340 retvm_if(!set_blocking_mode(false), false, "Failed to set non-blocking mode");
342 retvm_if(!set_recv_timeout(1), false, "Failed to set timeout");
344 /*retvm_if(!set_reuse_addr(), false, "Failed to reuse address"); */
346 _D("Created[%d]", m_sock_fd);
353 int socket::get_sock_type(void)
357 opt_len = sizeof(sock_type);
359 retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd);
361 if (getsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &sock_type, &opt_len) < 0) {
362 _ERRNO(errno, _E, "Failed to getsockopt from socket[%d]", m_sock_fd);
369 bool socket::set_recv_timeout(int sec)
371 struct timeval timeout = {sec, 0};
373 retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd);
375 if (setsockopt(m_sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
376 _ERRNO(errno, _E, "Failed to setsockopt[%d]", m_sock_fd);
383 bool socket::set_sock_type(int type)
386 opt_len = sizeof(type);
388 retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd);
390 if (setsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &type, opt_len) < 0) {
391 _ERRNO(errno, _E, "Failed to setsockopt[%d]", m_sock_fd);
398 bool socket::set_blocking_mode(bool blocking)
402 flags = fcntl(m_sock_fd, F_GETFL);
403 retvm_if(flags == -1, false, "Failed to fcntl(F_GETFL)[%d]", m_sock_fd);
405 flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
407 flags = fcntl(m_sock_fd, F_SETFL, flags);
408 retvm_if(flags == -1, false, "Failed to fcntl(F_SETFL)[%d]", m_sock_fd);
413 bool socket::has_connected(void)
416 socklen_t len = sizeof(so_error);
418 if (getsockopt(m_sock_fd, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) {
419 _E("Failed to call getsockopt[%d]", m_sock_fd);
424 _E("Failed to connect[%d] : %d", m_sock_fd, so_error);
431 bool socket::set_buffer_size(int type, int size)
433 retv_if(m_sock_fd < 0, false);
437 ret = setsockopt(m_sock_fd, SOL_SOCKET, type, &size, sizeof(size));
438 retvm_if(ret < 0, false, "Failed to call setsocketopt()");
443 int socket::get_buffer_size(int type)
445 retv_if(m_sock_fd < 0, false);
451 ret = getsockopt(m_sock_fd, SOL_SOCKET, type, &buf_size, &len);
452 retvm_if(ret < 0, -EPERM, "Failed to call getsocketopt()");
457 int socket::get_current_buffer_size(void)
459 retv_if(m_sock_fd < 0, false);
462 ioctl(m_sock_fd, TIOCOUTQ, &queue_size);