Remove TIDL for signal transmission
[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 pkgmgr_client_t* Connector::GetRawPc() {
234   return raw_pc_;
235 }
236
237 bool Connector::Activator::Connect() {
238   if (!Create())
239     return false;
240
241   SetTimeout(60 * 1000);
242
243   int retry_cnt = 3;
244   do {
245     int ret = TryConnect();
246     if (ret == 0) {
247       break;
248     } else if (ret < -1) {
249       _E("Maybe peer not launched or peer dead. path: %s, fd: %d",
250           PACKAGE_MANAGER_SOCKET_PATH, fd_);
251       // If requester is root, don't wait
252       if (getuid() == 0)
253         return false;
254
255       usleep(100 * 1000);
256       --retry_cnt;
257     } else if (ret < 0) {
258       _E("Failed to connect to socket: %s, fd: %d",
259           PACKAGE_MANAGER_SOCKET_PATH, fd_);
260       return false;
261     }
262   } while (retry_cnt > 0);
263
264   if (retry_cnt == 0) {
265     _E("Failed to connect with server");
266     return false;
267   }
268
269   return ReceiveReady();
270 }
271
272 bool Connector::Activator::Create() {
273   if (fd_ != -1)
274     return true;
275
276   fd_ = ::socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
277   if (fd_ < 0) {
278     _E("socket() is failed. errno: %d", errno);
279     return false;
280   }
281
282   addr_.sun_family = AF_UNIX;
283   snprintf(addr_.sun_path, sizeof(addr_.sun_path), "%s",
284       PACKAGE_MANAGER_SOCKET_PATH);
285   return true;
286 }
287
288 void Connector::Activator::SetTimeout(int timeout_msec) {
289   if (timeout_msec < 0) {
290     _E("Invalid timeout parameter");
291     return;
292   }
293
294   timeval timeout = {
295     .tv_sec = static_cast<time_t>(timeout_msec / 1000),
296     .tv_usec = static_cast<time_t>(timeout_msec % 1000) * 1000
297   };
298   if (setsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0)
299     _E("setsockopt() is failed, fd: %d, errno : %d", fd_, errno);
300 }
301
302 int Connector::Activator::TryConnect() {
303   int ret = connect(fd_, reinterpret_cast<sockaddr*>(&addr_), sizeof(addr_));
304   _E("ret = %d", ret);
305   if (ret < 0) {
306     if (errno != EAGAIN && errno != EINPROGRESS)
307       return -2;
308   }
309
310   return 0;
311 }
312
313
314 bool Connector::Activator::ReceiveReady() {
315   bool is_blocking;
316   if (fcntl(fd_, F_GETFL, 0) & O_NONBLOCK)
317     is_blocking = false;
318   else
319     is_blocking = true;
320
321   int retry_count = 20;
322   size_t len = 1;
323   char buffer[2] = {0,};
324   while (len) {
325     ssize_t bytes = recv(fd_, buffer, len, 0);
326     if (bytes == 0) {
327       _W("EOF. fd(%d)", fd_);
328       return -ECOMM;
329     }
330
331     if (bytes < 0) {
332       if (errno == EINTR || errno == EAGAIN) {
333         if (is_blocking && errno == EAGAIN) {
334           _E("Timed out. fd(%d)", fd_);
335           return -EAGAIN;
336         }
337
338         if (retry_count > 0) {
339           usleep(100 * 1000);
340           retry_count--;
341           continue;
342         }
343       }
344
345       _E("recv() is failed. fd(%d), errno(%d)", fd_, errno);
346       return -ECOMM;
347     }
348     _E("bytes: %d\n", bytes);
349     len -= bytes;
350   }
351
352   _E("Received: %s\n", buffer);
353
354   close(fd_);
355   fd_ = -1;
356
357   return true;
358 }
359
360 }  // namespace client
361 }  // namespace pkgmgr