Refactor slp-pkgmgr with tidl
[platform/core/appfw/slp-pkgmgr.git] / client / src / connector.cc
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
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 "connector.hh"
18
19 #include <fcntl.h>
20 #include <time.h>
21 #include <unistd.h>
22 #include <sys/socket.h>
23
24 #include "log.hh"
25
26 #define REGULAR_USER 5000
27
28 namespace {
29
30 constexpr const char SERVER_PROC_NAME[] = "org.tizen.appfw.pkgmgr";
31 constexpr const char PACKAGE_MANAGER_SOCKET_PATH[] = "/run/package-manager";
32
33 static int _is_system_user(void)
34 {
35   uid_t uid = getuid();
36
37   if (uid < REGULAR_USER)
38     return 1;
39   else
40     return 0;
41 }
42
43 static bool __is_system_type(pkgmgr_client_type type)
44 {
45   if (type == PC_REQUEST || _is_system_user())
46     return true;
47   else
48     return false;
49 }
50
51 }
52
53 namespace pkgmgr {
54 namespace client {
55
56 Connector::~Connector() = default;
57
58 std::string Connector::GenerateRequestId() const {
59   struct timeval tv;
60   gettimeofday(&tv, NULL);
61   long curtime = tv.tv_sec * 1000000 + tv.tv_usec;
62
63   return std::to_string(getpid()) + "_" + std::to_string(curtime);
64 }
65
66 void Connector::SetTep(std::string tep_path, bool tep_move) {
67   tep_path_ = std::move(tep_path);
68   tep_move_ = tep_move;
69 }
70
71 void Connector::SetTepArgs() {
72   argv_.push_back("-e");
73   argv_.push_back(tep_path_);
74   argv_.push_back("-M");
75   argv_.push_back(tep_move_ ? "tep_move" : "tep_copy");
76 }
77
78 void Connector::SetDebugMode() {
79   argv_.push_back("-G");
80 }
81
82 void Connector::SetSkipOptimization() {
83   argv_.push_back("-S");
84 }
85
86 const std::vector<std::string>& Connector::GetArgv() const {
87   return argv_;
88 }
89
90 pkg_proxy::PkgMgrAdmin* Connector::GetAdminProxy() {
91   if (!ConnectForAdmin())
92     return nullptr;
93
94   return admin_proxy_.get();
95 }
96
97 pkg_proxy::PkgMgr* Connector::GetInfoProxy() {
98   if (!ConnectForInfo())
99     return nullptr;
100
101   return info_proxy_.get();
102 }
103
104 pkg_proxy::PkgMgrForClearCache* Connector::GetCacheProxy() {
105   if (!ConnectForCache())
106     return nullptr;
107
108   return cache_proxy_.get();
109 }
110
111 pkg_proxy::DelayedResult* Connector::GetDelayedResultProxy() {
112   if (!ConnectForDelayedResult())
113     return nullptr;
114
115   return delayed_result_proxy_.get();
116 }
117
118 bool Connector::ConnectForAdmin() {
119   if (!admin_proxy_) {
120     admin_proxy_.reset(new pkg_proxy::PkgMgrAdmin(&conn_admin_listener_,
121         SERVER_PROC_NAME));
122   }
123
124   if (conn_admin_listener_.GetState() == ConnectionState::Connected)
125     return true;
126
127   if (!activator_.Connect())
128     return false;
129
130   try {
131     admin_proxy_->Connect(true);
132   } catch (const pkg_proxy::Exception& e) {
133     return false;
134   }
135
136   return true;
137 }
138
139 bool Connector::ConnectForInfo() {
140   if (!info_proxy_) {
141     info_proxy_.reset(new pkg_proxy::PkgMgr(&conn_info_listener_,
142         SERVER_PROC_NAME));
143   }
144
145   if (conn_info_listener_.GetState() == ConnectionState::Connected)
146     return true;
147
148   if (!activator_.Connect())
149     return false;
150
151   try {
152     info_proxy_->Connect(true);
153   } catch (const pkg_proxy::Exception& e) {
154     return false;
155   }
156
157   return true;
158 }
159
160 bool Connector::ConnectForCache() {
161   if (!cache_proxy_) {
162     cache_proxy_.reset(new pkg_proxy::PkgMgrForClearCache(&conn_cache_listener_,
163         SERVER_PROC_NAME));
164   }
165
166   if (conn_cache_listener_.GetState() == ConnectionState::Connected)
167     return true;
168
169   if (!activator_.Connect())
170     return false;
171
172   try {
173     cache_proxy_->Connect(true);
174   } catch (const pkg_proxy::Exception& e) {
175     return false;
176   }
177
178   return true;
179 }
180
181 bool Connector::ConnectForDelayedResult() {
182   if (!delayed_result_proxy_) {
183     delayed_result_proxy_.reset(new pkg_proxy::DelayedResult(
184         &conn_delayed_result_listener_, SERVER_PROC_NAME));
185   }
186
187   if (conn_delayed_result_listener_.GetState() == ConnectionState::Connected)
188     return true;
189
190   if (!activator_.Connect())
191     return false;
192
193   try {
194     delayed_result_proxy_->Connect(true);
195   } catch (const pkg_proxy::Exception& e) {
196     return false;
197   }
198
199   return true;
200 }
201
202 const std::unique_ptr<SignalReceiver>& Connector::GetSignalReceiver() {
203   if (!signal_receiver_)
204     signal_receiver_.reset(new SignalReceiver(__is_system_type(pc_type_)));
205
206   return signal_receiver_;
207 }
208
209 pkgmgr_client_type Connector::GetPcType() const {
210   return pc_type_;
211 }
212
213 std::vector<std::string>& Connector::GetResRemovePath() {
214   return res_remove_path_;
215 }
216
217 std::vector<std::string>& Connector::GetResCreateDir() {
218   return res_create_dir_;
219 }
220
221 std::vector<pp::ResPath>& Connector::GetResCopyPath() {
222   return res_copy_path_;
223 }
224
225 const std::string& Connector::GetTepPath() {
226   return tep_path_;
227 }
228
229 bool Connector::GetTepMove() {
230   return tep_move_;
231 }
232
233 bool Connector::Activator::Connect() {
234   if (!Create())
235     return false;
236
237   SetTimeout(60 * 1000);
238
239   int retry_cnt = 3;
240   do {
241     int ret = TryConnect();
242     if (ret == 0) {
243       break;
244     } else if (ret < -1) {
245       _E("Maybe peer not launched or peer dead. path: %s, fd: %d",
246           PACKAGE_MANAGER_SOCKET_PATH, fd_);
247       // If requester is root, don't wait
248       if (getuid() == 0)
249         return false;
250
251       usleep(100 * 1000);
252       --retry_cnt;
253     } else if (ret < 0) {
254       _E("Failed to connect to socket: %s, fd: %d",
255           PACKAGE_MANAGER_SOCKET_PATH, fd_);
256       return false;
257     }
258   } while (retry_cnt > 0);
259
260   if (retry_cnt == 0) {
261     _E("Failed to connect with server");
262     return false;
263   }
264
265   return ReceiveReady();
266 }
267
268 bool Connector::Activator::Create() {
269   if (fd_ != -1)
270     return true;
271
272   fd_ = ::socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
273   if (fd_ < 0) {
274     _E("socket() is failed. errno: %d", errno);
275     return false;
276   }
277
278   addr_.sun_family = AF_UNIX;
279   snprintf(addr_.sun_path, sizeof(addr_.sun_path), "%s",
280       PACKAGE_MANAGER_SOCKET_PATH);
281   return true;
282 }
283
284 void Connector::Activator::SetTimeout(int timeout_msec) {
285   if (timeout_msec < 0) {
286     _E("Invalid timeout parameter");
287     return;
288   }
289
290   timeval timeout = {
291     .tv_sec = static_cast<time_t>(timeout_msec / 1000),
292     .tv_usec = static_cast<time_t>(timeout_msec % 1000) * 1000
293   };
294   if (setsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0)
295     _E("setsockopt() is failed, fd: %d, errno : %d", fd_, errno);
296 }
297
298 int Connector::Activator::TryConnect() {
299   int ret = connect(fd_, reinterpret_cast<sockaddr*>(&addr_), sizeof(addr_));
300   _E("ret = %d", ret);
301   if (ret < 0) {
302     if (errno != EAGAIN && errno != EINPROGRESS)
303       return -2;
304   }
305
306   return 0;
307 }
308
309
310 bool Connector::Activator::ReceiveReady() {
311   bool is_blocking;
312   if (fcntl(fd_, F_GETFL, 0) & O_NONBLOCK)
313     is_blocking = false;
314   else
315     is_blocking = true;
316
317   int retry_count = 20;
318   size_t len = 1;
319   char buffer[2] = {0,};
320   while (len) {
321     ssize_t bytes = recv(fd_, buffer, len, 0);
322     if (bytes == 0) {
323       _W("EOF. fd(%d)", fd_);
324       return -ECOMM;
325     }
326
327     if (bytes < 0) {
328       if (errno == EINTR || errno == EAGAIN) {
329         if (is_blocking && errno == EAGAIN) {
330           _E("Timed out. fd(%d)", fd_);
331           return -EAGAIN;
332         }
333
334         if (retry_count > 0) {
335           usleep(100 * 1000);
336           retry_count--;
337           continue;
338         }
339       }
340
341       _E("recv() is failed. fd(%d), errno(%d)", fd_, errno);
342       return -ECOMM;
343     }
344     _E("bytes: %d\n", bytes);
345     len -= bytes;
346   }
347
348   _E("Received: %s\n", buffer);
349
350   close(fd_);
351   fd_ = -1;
352
353   return true;
354 }
355
356 }  // namespace client
357 }  // namespace pkgmgr