2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
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 "client_socket.hh"
21 #include <sys/socket.h>
22 #include <sys/types.h>
26 #include "utils/logging.hh"
28 #include "pkgmgrinfo_debug.h"
32 bool IsDBWriteRequest(pkgmgr_common::ReqType req_type) {
33 if (req_type != pkgmgr_common::ReqType::SET_PKG_INFO &&
34 req_type != pkgmgr_common::ReqType::SET_CERT_INFO &&
35 req_type != pkgmgr_common::ReqType::WRITE_QUERY)
43 namespace pkgmgr_common {
46 ClientSocket::ClientSocket(std::string path)
47 : AbstractSocket(std::move(path)) {}
49 void ClientSocket::SetTimeout(int timeout_msec) {
50 if (timeout_msec == -1)
53 if (timeout_msec < 0) {
54 LOG(ERROR) << "Invalid timeout_msec parameter";
58 struct timeval timeout = {
59 .tv_sec = static_cast<time_t>(timeout_msec / 1000),
60 .tv_usec = static_cast<suseconds_t>((timeout_msec % 1000) * 1000)};
62 if (setsockopt(fd_, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0)
63 LOG(ERROR) << "setsockopt() is failed. fd: " << fd_
64 << ", errno: " << errno;
67 int ClientSocket::GetTimeoutFromEnv() {
68 const char* timeout_str = getenv("PKGMGR_SOCKET_TIMEOUT");
69 if (timeout_str == nullptr)
72 int timeout_msec = atoi(timeout_str);
73 if (timeout_msec <= 0)
79 bool ClientSocket::Connect(ReqType req_type) {
83 int timeout = GetTimeoutFromEnv();
85 timeout = IsDBWriteRequest(req_type) ? 60 * 1000 : 5 * 1000;
90 int ret = TryConnection();
93 } else if (ret < -1) {
94 LOG(ERROR) << "Maybe peer not launched or peer dead. path: " << GetPath()
95 << ", fd: " << GetFd();
97 // If requester is root, don't wait
103 } else if (ret < 0) {
104 LOG(ERROR) << "Failed to connect to socket: " << GetPath()
105 << ", fd: " << GetFd();
108 } while (retry_cnt > 0);
110 return (retry_cnt > 0);
113 int ClientSocket::TryConnection() {
114 int flags = fcntl(fd_, F_GETFL, 0);
116 if (fcntl(fd_, F_SETFL, flags | O_NONBLOCK) != 0) {
117 LOG(ERROR) << "Failed to set flags: " << (flags | O_NONBLOCK) << " on fd: "
118 << fd_ << ", errno: " << errno;
123 connect(fd_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_));
124 if (fcntl(fd_, F_SETFL, flags) != 0) {
125 LOG(ERROR) << "Failed to set flags: " << flags << " on fd: " << fd_
126 << ", errno: " << errno;
130 if (errno != EAGAIN && errno != EINPROGRESS)
132 } else if (ret == 0) {
139 FD_SET(fd_, &readfds);
140 fd_set writefds = readfds;
141 struct timeval timeout = {0, 100 * 1000};
142 ret = select(fd_ + 1, &readfds, &writefds, NULL, &timeout);
148 if (FD_ISSET(fd_, &readfds) || FD_ISSET(fd_, &writefds)) {
150 socklen_t len = sizeof(error);
151 if (getsockopt(fd_, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
158 } // namespace socket
159 } // namespace pkgmgr_common