Modify CPUBoostingController
[platform/core/appfw/launchpad.git] / src / lib / launchpad-common / client_socket.cc
1 /*
2  * Copyright (c) 2023 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 #include "launchpad-common/client_socket.hh"
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <limits.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <sys/un.h>
25 #include <unistd.h>
26
27 #include "launchpad-common/log_private.hh"
28
29 namespace launchpad {
30 namespace {
31
32 constexpr const int MAX_RETRY_CNT = 2;
33
34 }  // namespace
35
36 ClientSocket::ClientSocket() {
37   fd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
38   if (fd_ < 0) {
39     int error = -errno;
40     _E("socket() is failed. errno(%d)", errno);
41     THROW(error);
42   }
43 }
44
45 ClientSocket::ClientSocket(int fd) : fd_(fd) {}
46
47 ClientSocket::~ClientSocket() {
48   Close();
49 }
50
51 void ClientSocket::Close() {
52   if (fd_ > -1) {
53     close(fd_);
54     fd_ = -1;
55   }
56 }
57
58 void ClientSocket::Connect(const std::string& endpoint) {
59   int flag = fcntl(fd_, F_GETFL, 0);
60   if (flag == -1) {
61     int ret = -errno;
62     _E("Failed to fcntl(%d, F_GETFL, 0). errno(%d)", fd_, errno);
63     THROW(ret);
64   }
65
66   fcntl(fd_, F_SETFL, flag | O_NONBLOCK);
67   struct sockaddr_un sockaddr = { 0, };
68   sockaddr.sun_family = AF_UNIX;
69   snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s",
70       endpoint.c_str());
71   struct sockaddr* sockaddr_ptr = reinterpret_cast<struct sockaddr*>(&sockaddr);
72   socklen_t len = static_cast<socklen_t>(sizeof(sockaddr));
73
74   int ret;
75   int retry = 2;
76   do {
77     ret = connect(fd_, sockaddr_ptr, len);
78     if (ret == 0)
79       break;
80
81     retry--;
82     ret = -errno;
83     usleep(100 * 1000);
84   } while (retry > 0);
85
86   fcntl(fd_, F_SETFL, flag);
87   if (ret < 0) {
88     _E("connect() is failed. errno(%d)", -ret);
89     THROW(ret);
90   }
91 }
92
93 int ClientSocket::Send(const void* buf, size_t size) {
94   const unsigned char* buffer = static_cast<const unsigned char*>(buf);
95   size_t len = size;
96   int retry_cnt = MAX_RETRY_CNT;
97   while (len) {
98     ssize_t bytes = send(fd_, buffer, len, MSG_NOSIGNAL | MSG_DONTWAIT);
99     if (bytes < 0) {
100       if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
101         if (retry_cnt > 0) {
102           retry_cnt--;
103           _E("send(): fd(%d), errno(%d). sleep and retry ...", fd_, errno);
104           usleep(10 * 1000);
105           continue;
106         }
107       }
108
109       _E("send() is failed. fd(%d), errno(%d)", fd_, errno);
110       return -ECOMM;
111     }
112
113     len -= bytes;
114     buffer += bytes;
115   }
116
117   return 0;
118 }
119
120 int ClientSocket::Receive(void* buf, size_t size) {
121   bool is_blocking;
122   if (fcntl(fd_, F_GETFL, 0) & O_NONBLOCK)
123     is_blocking = false;
124   else
125     is_blocking = true;
126
127   int retry_count = 20;
128   unsigned char* buffer = static_cast<unsigned char*>(buf);
129   size_t len = size;
130   while (len) {
131     ssize_t bytes = recv(fd_, buffer, len, 0);
132     if (bytes == 0) {
133       _W("EOF. fd(%d)", fd_);
134       return -ECOMM;
135     }
136
137     if (bytes < 0) {
138       if (errno == EINTR || errno == EAGAIN) {
139         if (is_blocking && errno == EAGAIN) {
140           _E("Timed out. fd(%d)", fd_);
141           return -EAGAIN;
142         }
143
144         if (retry_count > 0) {
145           usleep(100 * 1000);
146           retry_count--;
147           continue;
148         }
149       }
150
151       _E("recv() is failed. fd(%d), errno(%d)", fd_, errno);
152       return -ECOMM;
153     }
154
155     len -= bytes;
156     buffer += bytes;
157   }
158
159   return 0;
160 }
161
162
163 int ClientSocket::GetReceiveBufferSize() {
164   int value;
165   socklen_t len = sizeof(int);
166   int ret = getsockopt(fd_, SOL_SOCKET, SO_RCVBUF,
167       reinterpret_cast<void*>(&value), &len);
168   if (ret < 0) {
169     ret = -errno;
170     _E("getsockopt() is failed. errno(%d)", errno);
171     THROW(ret);
172   }
173
174   return value;
175 }
176
177 int ClientSocket::GetSendBufferSize() {
178   int value;
179   socklen_t len = sizeof(int);
180   int ret = getsockopt(fd_, SOL_SOCKET, SO_SNDBUF,
181       reinterpret_cast<void*>(&value), &len);
182   if (ret < 0) {
183     ret = -errno;
184     _E("getsockopt() is failed. errno(%d)", errno);
185     THROW(ret);
186   }
187
188   return value;
189 }
190
191 int ClientSocket::GetReceiveTimeout() {
192   struct timeval timeout = { 0, };
193   socklen_t len = static_cast<socklen_t>(sizeof(struct timeval));
194   int ret = getsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO,
195       reinterpret_cast<void*>(&timeout), &len);
196   if (ret < 0) {
197     ret = -errno;
198     _E("getsockopt() is failed. errno(%d)", errno);
199     THROW(ret);
200   }
201
202   int value = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
203   return value;
204 }
205
206 void ClientSocket::SetReceiveBufferSize(int size) {
207   socklen_t len = sizeof(size);
208   int ret = setsockopt(fd_, SOL_SOCKET, SO_RCVBUF, &size, len);
209   if (ret < 0) {
210     ret = -errno;
211     _E("setsockopt() is failed. errno(%d)", errno);
212     THROW(ret);
213   }
214 }
215
216 void ClientSocket::SetSendBufferSize(int size) {
217   socklen_t len = sizeof(size);
218   int ret = setsockopt(fd_, SOL_SOCKET, SO_SNDBUF, &size, len);
219   if (ret < 0) {
220     ret = -errno;
221     _E("setsockopt() is failed. errno(%d)", errno);
222     THROW(ret);
223   }
224 }
225
226 void ClientSocket::SetReceiveTimeout(int timeout) {
227   if (timeout == INT_MAX)
228     return;
229
230   if (timeout == -1)
231     timeout = 5000;
232
233   if (timeout < 0) {
234     _E("Invalid parameter");
235     THROW(-EINVAL);
236   }
237
238   struct timeval tv = {
239     .tv_sec = static_cast<time_t>(timeout / 1000),
240     .tv_usec = static_cast<suseconds_t>((timeout % 1000) * 1000)
241   };
242   socklen_t len = static_cast<socklen_t>(sizeof(struct timeval));
243   int ret = setsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO, &tv, len);
244   if (ret < 0) {
245     ret = -errno;
246     _E("setsockopt() is failed. errno(%d)", errno);
247     THROW(ret);
248   }
249 }
250
251 bool ClientSocket::IsClosed() const {
252   return fd_ < 0;
253 }
254
255 int ClientSocket::GetFd() const {
256   return fd_;
257 }
258
259 int ClientSocket::RemoveFd() {
260   int fd = fd_;
261   fd_ = -1;
262   return fd;
263 }
264
265 }  // namespace launchpad