Downgrade some frequently printed log's level
[platform/upstream/csr-framework.git] / src / framework / common / socket.cpp
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16 /*
17  * @file        socket.cpp
18  * @author      Kyungwook Tak (k.tak@samsung.com)
19  * @version     1.0
20  * @brief
21  */
22 #include "common/socket.h"
23
24 #include <sys/socket.h>
25 #include <sys/stat.h>
26 #include <sys/un.h>
27 #include <unistd.h>
28
29 #include <systemd/sd-daemon.h>
30
31 #include "common/audit/logger.h"
32 #include "common/exception.h"
33
34 namespace Csr {
35
36 namespace {
37
38 int g_sd_listen_fds = -1;
39
40 int createSystemdSocket(const std::string &path)
41 {
42         if (g_sd_listen_fds == -1)
43                 g_sd_listen_fds = ::sd_listen_fds(0);
44
45         if (g_sd_listen_fds < 0)
46                 ThrowExc(CSR_ERROR_SOCKET, "failed to sd_listen_fds");
47
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);
51                         return fd;
52                 }
53         }
54
55         ThrowExc(CSR_ERROR_SOCKET, "No useable socket were passed by systemd. path: " << path);
56 }
57
58 } // namespace anonymous
59
60 Socket Socket::create(SockId sockId, Socket::Type type)
61 {
62         switch (type) {
63         case Socket::Type::SERVER:
64                 return Socket(sockId);
65         case Socket::Type::CLIENT:
66                 return Socket::connect(sockId);
67         default:
68                 ThrowExc(CSR_ERROR_SOCKET, "Invalid type to Socket::create");
69         }
70 }
71
72 Socket::Socket(SockId sockId, int fd) : m_sockId(sockId), m_fd(fd)
73 {
74         if (this->m_fd < 0)
75                 ThrowExc(CSR_ERROR_SOCKET, "Socket fd from constructor is invalid!!");
76 }
77
78 Socket::Socket(SockId sockId) : m_sockId(sockId)
79 {
80         this->m_fd = createSystemdSocket(getSockDesc(this->m_sockId).path);
81 }
82
83 Socket::Socket(Socket &&other) noexcept : m_sockId(other.m_sockId), m_fd(other.m_fd)
84 {
85         other.m_fd = 0;
86 }
87
88 Socket &Socket::operator=(Socket &&other) noexcept
89 {
90         if (this == &other)
91                 return *this;
92
93         this->m_sockId = other.m_sockId;
94         this->m_fd = other.m_fd;
95         other.m_fd = 0;
96
97         return *this;
98 }
99
100 Socket::~Socket()
101 {
102         if (this->m_fd == 0)
103                 return;
104
105         DEBUG("Close socket of fd: " << this->m_fd);
106         ::close(m_fd);
107 }
108
109 Socket Socket::accept(void) const
110 {
111         int fd = ::accept(this->m_fd, nullptr, nullptr);
112
113         if (fd < 0)
114                 ThrowExc(CSR_ERROR_SOCKET, "socket on fd[" << this->m_fd << "] accept failed "
115                                  "with errno: " << errno);
116
117         DEBUG("Accept client success with fd: " << fd);
118
119         return Socket(this->m_sockId, fd);
120 }
121
122 Socket Socket::connect(SockId sockId)
123 {
124         const auto &path = getSockDesc(sockId).path;
125
126         if (path.size() >= sizeof(sockaddr_un::sun_path))
127                 ThrowExc(CSR_ERROR_SERVER, "socket path size too long!");
128
129         int fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
130
131         if (fd < 0)
132                 ThrowExc(CSR_ERROR_SOCKET, "Socket create failed with errno: " << errno);
133
134         sockaddr_un addr;
135         addr.sun_family = AF_UNIX;
136
137         strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path));
138
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);
143
144         INFO("Connect to CSR server success with fd:" << fd);
145
146         return Socket(sockId, fd);
147 }
148
149 SockId Socket::getSockId(void) const noexcept
150 {
151         return this->m_sockId;
152 }
153
154 int Socket::getFd(void) const noexcept
155 {
156         return this->m_fd;
157 }
158
159 RawBuffer Socket::read(void) const
160 {
161         size_t total = 0;
162         size_t size = 0;
163
164         auto bytes = ::read(this->m_fd, &size, sizeof(size));
165         if (bytes < 0)
166                 ThrowExc(CSR_ERROR_SOCKET, "Socket data size read failed on fd[" << this->m_fd <<
167                                  "] with errno: " << errno);
168
169         RawBuffer data(size, 0);
170         auto buf = reinterpret_cast<char *>(data.data());
171
172         while (total < size) {
173                 bytes = ::read(this->m_fd, buf + total, size - total);
174
175                 if (bytes < 0) {
176                         if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
177                                 continue;
178                         else
179                                 ThrowExc(CSR_ERROR_SOCKET, "Socket read failed on fd[" << this->m_fd <<
180                                                  "] with errno: " << errno);
181                 }
182
183                 total += bytes;
184         }
185
186         data.resize(total);
187
188         DEBUG("Read data of size[" << total
189                   << "] from stream on socket fd[" << this->m_fd << "] done.");
190
191         return data;
192 }
193
194 void Socket::write(const RawBuffer &data) const
195 {
196         size_t total = 0;
197
198         auto buf = reinterpret_cast<const char *>(data.data());
199         auto size = data.size();
200
201         auto bytes = ::write(this->m_fd, &size, sizeof(size));
202         if (bytes < 0)
203                 ThrowExcWarn(CSR_ERROR_SOCKET, "Socket data size write failed on fd[" << this->m_fd <<
204                                  "] with errno: " << errno);
205
206         while (total < size) {
207                 bytes = ::write(this->m_fd, buf + total, size - total);
208
209                 if (bytes < 0) {
210                         if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
211                                 continue;
212                         else
213                                 ThrowExcWarn(CSR_ERROR_SOCKET, "Socket write failed on fd[" << this->m_fd <<
214                                                  "] with errno: " << errno);
215                 }
216
217                 total += bytes;
218         }
219
220         DEBUG("Write data of size[" << total <<
221                   "] to stream on socket fd[" << this->m_fd << "] done.");
222 }
223
224 }