Improve performance
[platform/core/appfw/pkgmgr-info.git] / src / client / pkginfo_client.cc
1 // Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache-2.0 license that can be
3 // found in the LICENSE file.
4
5 #include "pkginfo_client.hh"
6
7 #include <parcel.hh>
8 #include <vconf.h>
9
10 #include <string>
11
12 #include "parcelable_factory.hh"
13 #include "get_appinfo_request_handler.hh"
14 #include "get_cert_request_handler.hh"
15 #include "get_depinfo_request_handler.hh"
16 #include "get_pkginfo_request_handler.hh"
17 #include "query_request_handler.hh"
18 #include "set_cert_request_handler.hh"
19 #include "set_pkginfo_request_handler.hh"
20 #include "system_locale.hh"
21 #include "ready_checker.hh"
22 #include "pkgmgrinfo_debug.h"
23
24 namespace pkgmgr_client {
25
26 constexpr const char SOCK_PATH[] = "/run/pkgmgr-info-server";
27 constexpr const char SERVER_READY[] = "/run/.pkginfo_server_ready";
28
29 PkgInfoClient::PkgInfoClient(
30     std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcel,
31     uid_t uid, pkgmgr_common::ReqType req_type)
32     : parcel_(parcel),
33       result_parcel_(nullptr),
34       uid_(uid),
35       req_type_(req_type),
36       is_offline_(false) {
37   socket_ = std::make_unique<pkgmgr_common::socket::ClientSocket>(SOCK_PATH);
38 }
39
40 bool PkgInfoClient::SendRequest() {
41   static pkgmgr_common::ReadyChecker check_server(SERVER_READY);
42   if (socket_ == nullptr) {
43     LOGE("Socket is not ready");
44     return false;
45   }
46
47   if (!check_server.IsReady()) {
48     LOGW("Server is not ready, try to direct access");
49     is_offline_ = true;
50     return RequestHandlerDirectAccess();
51   }
52   if (!socket_->Connect()) {
53     LOGE("Failed to connect client socket, try to direct access");
54     is_offline_ = true;
55     return RequestHandlerDirectAccess();
56   }
57
58   if (socket_->SendData(&req_type_, sizeof(req_type_)) != 0) {
59     LOGE("fail to send data");
60     return false;
61   }
62
63   tizen_base::Parcel p;
64   p.WriteParcelable(*parcel_.get());
65   const auto& raw = p.GetRaw();
66   int len = raw.size();
67
68   if (socket_->SendData(&len, sizeof(len)) != 0) {
69     LOGE("fail to send data");
70     return false;
71   }
72
73   if (socket_->SendData(&raw[0], len) != 0) {
74     LOGE("Fail to send data");
75     return false;
76   }
77
78   return true;
79 }
80
81 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable>
82 PkgInfoClient::GetResultParcel() {
83   if (is_offline_)
84     return result_parcel_;
85
86   if (socket_ == nullptr) {
87     LOGE("Socket is not ready");
88     return nullptr;
89   }
90   int len = 0;
91   if (socket_->ReceiveData(&len, sizeof(len)) != 0 || len <= 0) {
92     LOGE("Fail to receive data");
93     return nullptr;
94   }
95
96   unsigned char* raw = new (std::nothrow) unsigned char[len];
97   if (raw == nullptr) {
98     LOGE("Out of memory");
99     return nullptr;
100   }
101
102   if (socket_->ReceiveData(raw, len) != 0) {
103     LOGE("Fail to receive data");
104     delete[] raw;
105     return nullptr;
106   }
107
108   auto res = pkgmgr_common::parcel::ParcelableFactory::GetInst().CreateParcel(
109       raw, len);
110   delete[] raw;
111
112   return res;
113 }
114
115 bool PkgInfoClient::RequestHandlerDirectAccess() {
116   std::unique_ptr<pkgmgr_server::request_handler::AbstractRequestHandler>
117       handler;
118   switch (req_type_) {
119     case pkgmgr_common::ReqType::GET_PKG_INFO:
120       handler.reset(
121           new pkgmgr_server::request_handler::GetPkginfoRequestHandler());
122       break;
123     case pkgmgr_common::ReqType::GET_APP_INFO:
124       handler.reset(
125           new pkgmgr_server::request_handler::GetAppinfoRequestHandler());
126       break;
127     case pkgmgr_common::ReqType::SET_PKG_INFO:
128       handler.reset(
129           new pkgmgr_server::request_handler::SetPkginfoRequestHandler());
130       break;
131     case pkgmgr_common::ReqType::SET_CERT_INFO:
132       handler.reset(
133           new pkgmgr_server::request_handler::SetCertRequestHandler());
134       break;
135     case pkgmgr_common::ReqType::GET_CERT_INFO:
136       handler.reset(
137           new pkgmgr_server::request_handler::GetCertRequestHandler());
138       break;
139     case pkgmgr_common::ReqType::GET_PKG_DEP_INFO:
140       handler.reset(
141           new pkgmgr_server::request_handler::GetDepinfoRequestHandler());
142       break;
143     case pkgmgr_common::ReqType::QUERY:
144       handler.reset(new pkgmgr_server::request_handler::QueryRequestHandler());
145       break;
146     default:
147       handler.reset(nullptr);
148       break;
149   }
150
151   if (handler == nullptr) {
152     LOGE("Can't reset handler with type[%d]", req_type_);
153     return false;
154   }
155
156   tizen_base::Parcel p;
157   p.WriteParcelable(*parcel_.get());
158   std::vector<uint8_t> raw = p.GetRaw();
159
160   handler->HandleRequest(&raw[0], raw.size(),
161       pkgmgr_common::SystemLocale::GetInst().Get());
162   auto result = handler->ExtractResult();
163   if (result.size() == 0)
164     return true;
165
166   result_parcel_.reset(pkgmgr_common::parcel::ParcelableFactory::GetInst()
167       .CreateParcel(&result[0], result.size())
168       .release());
169
170   return true;
171 }
172
173 }  // namespace pkgmgr_client