2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
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.
17 #include "connector.hh"
22 #include <sys/socket.h>
26 #define REGULAR_USER 5000
30 constexpr const char SERVER_PROC_NAME[] = "org.tizen.appfw.pkgmgr";
31 constexpr const char PACKAGE_MANAGER_SOCKET_PATH[] = "/run/package-manager";
33 static int _is_system_user(void)
37 if (uid < REGULAR_USER)
43 static bool __is_system_type(pkgmgr_client_type type)
45 if (type == PC_REQUEST || _is_system_user())
56 Connector::~Connector() = default;
58 std::string Connector::GenerateRequestId() const {
60 gettimeofday(&tv, NULL);
61 long curtime = tv.tv_sec * 1000000 + tv.tv_usec;
63 return std::to_string(getpid()) + "_" + std::to_string(curtime);
66 void Connector::SetTep(std::string tep_path, bool tep_move) {
67 tep_path_ = std::move(tep_path);
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");
78 void Connector::SetDebugMode() {
79 argv_.push_back("-G");
82 void Connector::SetSkipOptimization() {
83 argv_.push_back("-S");
86 const std::vector<std::string>& Connector::GetArgv() const {
90 pkg_proxy::PkgMgrAdmin* Connector::GetAdminProxy() {
91 if (!ConnectForAdmin())
94 return admin_proxy_.get();
97 pkg_proxy::PkgMgr* Connector::GetInfoProxy() {
98 if (!ConnectForInfo())
101 return info_proxy_.get();
104 pkg_proxy::PkgMgrForClearCache* Connector::GetCacheProxy() {
105 if (!ConnectForCache())
108 return cache_proxy_.get();
111 pkg_proxy::DelayedResult* Connector::GetDelayedResultProxy() {
112 if (!ConnectForDelayedResult())
115 return delayed_result_proxy_.get();
118 bool Connector::ConnectForAdmin() {
120 admin_proxy_.reset(new pkg_proxy::PkgMgrAdmin(&conn_admin_listener_,
124 if (conn_admin_listener_.GetState() == ConnectionState::Connected)
127 if (!activator_.Connect())
131 admin_proxy_->Connect(true);
132 } catch (const pkg_proxy::Exception& e) {
139 bool Connector::ConnectForInfo() {
141 info_proxy_.reset(new pkg_proxy::PkgMgr(&conn_info_listener_,
145 if (conn_info_listener_.GetState() == ConnectionState::Connected)
148 if (!activator_.Connect())
152 info_proxy_->Connect(true);
153 } catch (const pkg_proxy::Exception& e) {
160 bool Connector::ConnectForCache() {
162 cache_proxy_.reset(new pkg_proxy::PkgMgrForClearCache(&conn_cache_listener_,
166 if (conn_cache_listener_.GetState() == ConnectionState::Connected)
169 if (!activator_.Connect())
173 cache_proxy_->Connect(true);
174 } catch (const pkg_proxy::Exception& e) {
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));
187 if (conn_delayed_result_listener_.GetState() == ConnectionState::Connected)
190 if (!activator_.Connect())
194 delayed_result_proxy_->Connect(true);
195 } catch (const pkg_proxy::Exception& e) {
202 //const std::unique_ptr<SignalReceiver>& Connector::GetSignalReceiver() {
203 // if (!signal_receiver_)
204 // signal_receiver_.reset(new SignalReceiver(__is_system_type(pc_type_)));
206 // return signal_receiver_;
209 pkgmgr_client_type Connector::GetPcType() const {
213 std::vector<std::string>& Connector::GetResRemovePath() {
214 return res_remove_path_;
217 std::vector<std::string>& Connector::GetResCreateDir() {
218 return res_create_dir_;
221 std::vector<pp::ResPath>& Connector::GetResCopyPath() {
222 return res_copy_path_;
225 const std::string& Connector::GetTepPath() {
229 bool Connector::GetTepMove() {
233 pkgmgr_client_t* Connector::GetRawPc() {
237 bool Connector::Activator::Connect() {
241 SetTimeout(60 * 1000);
245 int ret = TryConnect();
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
257 } else if (ret < 0) {
258 _E("Failed to connect to socket: %s, fd: %d",
259 PACKAGE_MANAGER_SOCKET_PATH, fd_);
262 } while (retry_cnt > 0);
264 if (retry_cnt == 0) {
265 _E("Failed to connect with server");
269 return ReceiveReady();
272 bool Connector::Activator::Create() {
276 fd_ = ::socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
278 _E("socket() is failed. errno: %d", errno);
282 addr_.sun_family = AF_UNIX;
283 snprintf(addr_.sun_path, sizeof(addr_.sun_path), "%s",
284 PACKAGE_MANAGER_SOCKET_PATH);
288 void Connector::Activator::SetTimeout(int timeout_msec) {
289 if (timeout_msec < 0) {
290 _E("Invalid timeout parameter");
295 .tv_sec = static_cast<time_t>(timeout_msec / 1000),
296 .tv_usec = static_cast<time_t>(timeout_msec % 1000) * 1000
298 if (setsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0)
299 _E("setsockopt() is failed, fd: %d, errno : %d", fd_, errno);
302 int Connector::Activator::TryConnect() {
303 int ret = connect(fd_, reinterpret_cast<sockaddr*>(&addr_), sizeof(addr_));
306 if (errno != EAGAIN && errno != EINPROGRESS)
314 bool Connector::Activator::ReceiveReady() {
316 if (fcntl(fd_, F_GETFL, 0) & O_NONBLOCK)
321 int retry_count = 20;
323 char buffer[2] = {0,};
325 ssize_t bytes = recv(fd_, buffer, len, 0);
327 _W("EOF. fd(%d)", fd_);
332 if (errno == EINTR || errno == EAGAIN) {
333 if (is_blocking && errno == EAGAIN) {
334 _E("Timed out. fd(%d)", fd_);
338 if (retry_count > 0) {
345 _E("recv() is failed. fd(%d), errno(%d)", fd_, errno);
348 _E("bytes: %d\n", bytes);
352 _E("Received: %s\n", buffer);
360 } // namespace client
361 } // namespace pkgmgr