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.
5 #include "pkginfo_client.hh"
14 #include "parcelable_factory.hh"
15 #include "system_locale.hh"
16 #include "ready_checker.hh"
17 #include "utils/logging.hh"
19 #include "pkgmgrinfo_debug.h"
20 #include "pkgmgrinfo_private.h"
22 #define LIBPKGMGR_INFO LIB_PATH "/libpkgmgr-info-server.so.0"
23 #define DIRECT_ACCESS_FUNC "_request_handler_direct_access"
25 namespace pkgmgr_client {
27 constexpr const char SOCK_PATH[] = "/run/pkgmgr-info-server";
28 constexpr const char SERVER_READY[] = "/run/.pkginfo_server_ready";
30 PkgInfoClient::PkgInfoClient(
31 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcel,
32 uid_t uid, pkgmgr_common::ReqType req_type)
34 result_parcel_(nullptr),
38 socket_ = std::make_unique<pkgmgr_common::socket::ClientSocket>(SOCK_PATH);
41 bool PkgInfoClient::SendRequest() {
42 static pkgmgr_common::ReadyChecker check_server(SERVER_READY);
43 if (socket_ == nullptr) {
44 LOG(ERROR) << "Socket is not ready";
49 p.WriteParcelable(*parcel_.get());
50 const auto& raw = p.GetRaw();
53 // CREATE_DB request type need to be executed directly by the caller
54 if (req_type_ == pkgmgr_common::ReqType::CREATE_DB) {
56 return RequestHandlerDirectAccess(p.GetRaw());
59 if (!check_server.IsReady()) {
60 LOG(WARNING) << "Server is not ready, try to direct access";
62 return RequestHandlerDirectAccess(p.GetRaw());
65 LOG(WARNING) << "Try to send request, Request type: "
66 << pkgmgr_common::ReqTypeToString(req_type_);
68 if (!socket_->Connect(req_type_)) {
69 LOG(ERROR) << "Failed to connect client socket, try to direct access";
71 return RequestHandlerDirectAccess(p.GetRaw());
74 if (socket_->SendData(&req_type_, sizeof(req_type_)) != 0) {
75 LOG(ERROR) << "fail to send data";
79 if (socket_->SendData(&len, sizeof(len)) != 0) {
80 LOG(ERROR) << "fail to send data";
84 if (socket_->SendData(&raw[0], len) != 0) {
85 LOG(ERROR) << "Fail to send data";
92 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable>
93 PkgInfoClient::GetResultParcel() {
95 return result_parcel_;
97 if (socket_ == nullptr) {
98 LOG(ERROR) << "Socket is not ready";
103 if (socket_->ReceiveData(&len, sizeof(len)) != 0 || len <= 0) {
104 LOG(ERROR) << "Fail to receive data";
108 unsigned char* raw = new (std::nothrow) unsigned char[len];
109 if (raw == nullptr) {
110 LOG(ERROR) << "Out of memory";
114 if (socket_->ReceiveData(raw, len) != 0) {
115 LOG(ERROR) << "Fail to receive data";
120 auto res = pkgmgr_common::parcel::ParcelableFactory::GetInst().CreateParcel(
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 *);
132 if (handle == nullptr) {
133 handle = dlopen(LIBPKGMGR_INFO, RTLD_GLOBAL | RTLD_LAZY);
135 LOG(ERROR) << "Failed to open library: " << LIBPKGMGR_INFO
136 << ", : " << dlerror();
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 "
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())));
159 } // namespace pkgmgr_client