Release version 0.22.21
[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 <dlfcn.h>
8
9 #include <parcel.hh>
10 #include <vconf.h>
11
12 #include <string>
13
14 #include "parcelable_factory.hh"
15 #include "system_locale.hh"
16 #include "ready_checker.hh"
17 #include "utils/logging.hh"
18
19 #include "pkgmgrinfo_debug.h"
20 #include "pkgmgrinfo_private.h"
21
22 #define LIBPKGMGR_INFO LIB_PATH "/libpkgmgr-info-server.so.0"
23 #define DIRECT_ACCESS_FUNC "_request_handler_direct_access"
24
25 namespace pkgmgr_client {
26
27 constexpr const char SOCK_PATH[] = "/run/pkgmgr-info-server";
28 constexpr const char SERVER_READY[] = "/run/.pkginfo_server_ready";
29
30 PkgInfoClient::PkgInfoClient(
31     std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcel,
32     uid_t uid, pkgmgr_common::ReqType req_type)
33     : parcel_(parcel),
34       result_parcel_(nullptr),
35       uid_(uid),
36       req_type_(req_type),
37       is_offline_(false) {
38   socket_ = std::make_unique<pkgmgr_common::socket::ClientSocket>(SOCK_PATH);
39 }
40
41 bool PkgInfoClient::SendRequest() {
42   static pkgmgr_common::ReadyChecker check_server(SERVER_READY);
43   if (socket_ == nullptr) {
44     LOG(ERROR) << "Socket is not ready";
45     return false;
46   }
47
48   tizen_base::Parcel p;
49   p.WriteParcelable(*parcel_.get());
50   const auto& raw = p.GetRaw();
51   int len = raw.size();
52
53   // CREATE_DB request type need to be executed directly by the caller
54   if (req_type_ == pkgmgr_common::ReqType::CREATE_DB) {
55     is_offline_ = true;
56     return RequestHandlerDirectAccess(p.GetRaw());
57   }
58
59   if (!check_server.IsReady()) {
60     LOG(WARNING) << "Server is not ready, try to direct access";
61     is_offline_ = true;
62     return RequestHandlerDirectAccess(p.GetRaw());
63   }
64
65   LOG(WARNING) << "Try to send request, Request type: "
66       << pkgmgr_common::ReqTypeToString(req_type_);
67
68   if (!socket_->Connect(req_type_)) {
69     LOG(ERROR) << "Failed to connect client socket, try to direct access";
70     is_offline_ = true;
71     return RequestHandlerDirectAccess(p.GetRaw());
72   }
73
74   if (socket_->SendData(&req_type_, sizeof(req_type_)) != 0) {
75     LOG(ERROR) << "fail to send data";
76     return false;
77   }
78
79   if (socket_->SendData(&len, sizeof(len)) != 0) {
80     LOG(ERROR) << "fail to send data";
81     return false;
82   }
83
84   if (socket_->SendData(&raw[0], len) != 0) {
85     LOG(ERROR) << "Fail to send data";
86     return false;
87   }
88
89   return true;
90 }
91
92 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable>
93 PkgInfoClient::GetResultParcel() {
94   if (is_offline_)
95     return result_parcel_;
96
97   if (socket_ == nullptr) {
98     LOG(ERROR) << "Socket is not ready";
99     return nullptr;
100   }
101
102   int len = 0;
103   if (socket_->ReceiveData(&len, sizeof(len)) != 0 || len <= 0) {
104     LOG(ERROR) << "Fail to receive data";
105     return nullptr;
106   }
107
108   unsigned char* raw = new (std::nothrow) unsigned char[len];
109   if (raw == nullptr) {
110     LOG(ERROR) << "Out of memory";
111     return nullptr;
112   }
113
114   if (socket_->ReceiveData(raw, len) != 0) {
115     LOG(ERROR) << "Fail to receive data";
116     delete[] raw;
117     return nullptr;
118   }
119
120   auto res = pkgmgr_common::parcel::ParcelableFactory::GetInst().CreateParcel(
121       raw, len);
122   delete[] raw;
123
124   return res;
125 }
126
127 bool PkgInfoClient::RequestHandlerDirectAccess(
128     const std::vector<uint8_t>& raw) {
129   static void* handle = nullptr;
130   static void* (*dl_func)(int, const unsigned char*, int, const char *);
131
132   if (handle == nullptr) {
133     handle = dlopen(LIBPKGMGR_INFO, RTLD_GLOBAL | RTLD_LAZY);
134     if (!handle) {
135       LOG(ERROR) << "Failed to open library: " << LIBPKGMGR_INFO
136           << ", : " << dlerror();
137       return false;
138     }
139     dl_func = reinterpret_cast<void* (*)(
140         int, const unsigned char*, int, const char *)>(
141             dlsym(handle, DIRECT_ACCESS_FUNC));
142     if (dl_func == nullptr) {
143       LOG(ERROR) << "cannot find " << DIRECT_ACCESS_FUNC << " symbol in "
144           << LIBPKGMGR_INFO;
145       dlclose(handle);
146       handle = nullptr;
147       return false;
148     }
149   }
150
151   result_parcel_.reset(
152       reinterpret_cast<pkgmgr_common::parcel::AbstractParcelable *>(
153           dl_func(req_type_, &raw[0], raw.size(),
154               pkgmgr_common::SystemLocale::GetInst(false).Get().c_str())));
155
156   return true;
157 }
158
159 }  // namespace pkgmgr_client