2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
18 * @author Kyungwook Tak (k.tak@samsung.com)
22 #include "common/socket.h"
24 #include <sys/socket.h>
29 #include <systemd/sd-daemon.h>
31 #include "common/audit/logger.h"
32 #include "common/exception.h"
38 int g_sd_listen_fds = -1;
40 int createSystemdSocket(const std::string &path)
42 if (g_sd_listen_fds == -1)
43 g_sd_listen_fds = ::sd_listen_fds(0);
45 if (g_sd_listen_fds < 0)
46 ThrowExc(CSR_ERROR_SOCKET, "failed to sd_listen_fds");
48 for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + g_sd_listen_fds; ++fd) {
49 if (::sd_is_socket_unix(fd, SOCK_STREAM, 1, path.c_str(), 0) > 0) {
50 INFO("service's systemd socket found with fd: " << fd);
55 ThrowExc(CSR_ERROR_SOCKET, "No useable socket were passed by systemd. path: " << path);
58 } // namespace anonymous
60 Socket Socket::create(SockId sockId, Socket::Type type)
63 case Socket::Type::SERVER:
64 return Socket(sockId);
65 case Socket::Type::CLIENT:
66 return Socket::connect(sockId);
68 ThrowExc(CSR_ERROR_SOCKET, "Invalid type to Socket::create");
72 Socket::Socket(SockId sockId, int fd) : m_sockId(sockId), m_fd(fd)
75 ThrowExc(CSR_ERROR_SOCKET, "Socket fd from constructor is invalid!!");
78 Socket::Socket(SockId sockId) : m_sockId(sockId)
80 this->m_fd = createSystemdSocket(getSockDesc(this->m_sockId).path);
83 Socket::Socket(Socket &&other) noexcept : m_sockId(other.m_sockId), m_fd(other.m_fd)
88 Socket &Socket::operator=(Socket &&other) noexcept
93 this->m_sockId = other.m_sockId;
94 this->m_fd = other.m_fd;
105 DEBUG("Close socket of fd: " << this->m_fd);
109 Socket Socket::accept(void) const
111 int fd = ::accept(this->m_fd, nullptr, nullptr);
114 ThrowExc(CSR_ERROR_SOCKET, "socket on fd[" << this->m_fd << "] accept failed "
115 "with errno: " << errno);
117 DEBUG("Accept client success with fd: " << fd);
119 return Socket(this->m_sockId, fd);
122 Socket Socket::connect(SockId sockId)
124 const auto &path = getSockDesc(sockId).path;
126 if (path.size() >= sizeof(sockaddr_un::sun_path))
127 ThrowExc(CSR_ERROR_SERVER, "socket path size too long!");
129 int fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
132 ThrowExc(CSR_ERROR_SOCKET, "Socket create failed with errno: " << errno);
135 addr.sun_family = AF_UNIX;
137 strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path));
139 if (::connect(fd, reinterpret_cast<sockaddr *>(&addr),
140 sizeof(sockaddr_un)) == -1)
141 ThrowExc(CSR_ERROR_SOCKET, "Socket[" << path << "] connect failed "
142 "with errno: " << errno);
144 INFO("Connect to CSR server success with fd:" << fd);
146 return Socket(sockId, fd);
149 SockId Socket::getSockId(void) const noexcept
151 return this->m_sockId;
154 int Socket::getFd(void) const noexcept
159 RawBuffer Socket::read(void) const
164 auto bytes = ::read(this->m_fd, &size, sizeof(size));
166 ThrowExc(CSR_ERROR_SOCKET, "Socket data size read failed on fd[" << this->m_fd <<
167 "] with errno: " << errno);
169 RawBuffer data(size, 0);
170 auto buf = reinterpret_cast<char *>(data.data());
172 while (total < size) {
173 bytes = ::read(this->m_fd, buf + total, size - total);
176 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
179 ThrowExc(CSR_ERROR_SOCKET, "Socket read failed on fd[" << this->m_fd <<
180 "] with errno: " << errno);
188 DEBUG("Read data of size[" << total
189 << "] from stream on socket fd[" << this->m_fd << "] done.");
194 void Socket::write(const RawBuffer &data) const
198 auto buf = reinterpret_cast<const char *>(data.data());
199 auto size = data.size();
201 auto bytes = ::write(this->m_fd, &size, sizeof(size));
203 ThrowExcWarn(CSR_ERROR_SOCKET, "Socket data size write failed on fd[" << this->m_fd <<
204 "] with errno: " << errno);
206 while (total < size) {
207 bytes = ::write(this->m_fd, buf + total, size - total);
210 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
213 ThrowExcWarn(CSR_ERROR_SOCKET, "Socket write failed on fd[" << this->m_fd <<
214 "] with errno: " << errno);
220 DEBUG("Write data of size[" << total <<
221 "] to stream on socket fd[" << this->m_fd << "] done.");