Change log header to pkgmgrinfo_debug.h
[platform/core/appfw/pkgmgr-info.git] / src / common / socket / abstract_socket.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <limits.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include "pkgmgrinfo_debug.h"
25 #include "abstract_socket.hh"
26
27 namespace pkgmgr_common {
28 namespace socket {
29
30 AbstractSocket::AbstractSocket(std::string path)
31     : path_(std::move(path)), fd_(-1), addr_{} {}
32
33 AbstractSocket::AbstractSocket(int fd) : fd_(fd), addr_{} {}
34
35 AbstractSocket::~AbstractSocket() {}
36
37 int AbstractSocket::SendData(const void* buf, unsigned int size) {
38   auto buffer = static_cast<const unsigned char*>(buf);
39   unsigned int left = size;
40   while (left) {
41     ssize_t send_byte = send(fd_, buffer, left, MSG_NOSIGNAL);
42     if (send_byte < 0) {
43       LOGE("send() is failed. fd(%d), errno(%d)", fd_, errno);
44       return -ECOMM;
45     }
46
47     left -= send_byte;
48     buffer += send_byte;
49   }
50
51   return 0;
52 }
53
54 int AbstractSocket::ReceiveData(void* buf, unsigned int size) {
55   bool is_blocking = true;
56   if (fcntl(fd_, F_GETFL, 0) & O_NONBLOCK) is_blocking = false;
57
58   auto buffer = static_cast<unsigned char*>(buf);
59   unsigned int left = size;
60   while (left) {
61     ssize_t recv_byte = recv(fd_, buffer, left, 0);
62     if (recv_byte == 0) {
63       LOGW("Socket was disconnected. fd(%d), errno(%d)", fd_, errno);
64       return -errno;
65     } else if (recv_byte < 0) {
66       if (errno == EINTR) {
67         continue;
68       } else if (errno == EAGAIN) {
69         if (is_blocking) {
70           LOGE("Timed out. fd(%d), errno(%d)", fd_, errno);
71           return -errno;
72         }
73
74         continue;
75       }
76
77       LOGE("recv() is failed. fd(%d), errno(%d)", fd_, errno);
78       return -ECOMM;
79     }
80
81     left -= recv_byte;
82     buffer += recv_byte;
83   }
84
85   return 0;
86 }
87
88 int AbstractSocket::GetFd() { return fd_; }
89
90 std::string AbstractSocket::GetPath() { return path_; }
91
92 pid_t AbstractSocket::GetPID() {
93   int r;
94   struct ucred cred = {};
95   socklen_t len = sizeof(cred);
96
97   r = getsockopt(fd_, SOL_SOCKET, SO_PEERCRED, &cred, &len);
98   if (r < 0) {
99     LOGE("getsockopt has failed, errno[%d]", errno);
100     return -1;
101   }
102
103   return cred.pid;
104 }
105
106 void AbstractSocket::SetOption() {
107   int size = 2048;
108   int ret = setsockopt(fd_, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
109   if (ret < 0) {
110     LOGE("setsockopt() is failed. fd(%d), errno(%d)", fd_, errno);
111     return;
112   }
113
114   ret = setsockopt(fd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
115   if (ret < 0) LOGE("setsockopt() is failed. fd(%d), errno(%d)", fd_, errno);
116 }
117
118 int AbstractSocket::Create() {
119   if (fd_ != -1) return 0;
120   fd_ = ::socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
121   if (fd_ < 0) {
122     LOGE("socket() is failed. errno(%d)", errno);
123     return fd_;
124   }
125
126   addr_.sun_family = AF_UNIX;
127   snprintf(addr_.sun_path, sizeof(addr_.sun_path), "%s", path_.c_str());
128   SetOption();
129   return 0;
130 }
131
132 void AbstractSocket::Disconnect() {
133   if (fd_ > 0) {
134     LOGW("Close fd(%d)", fd_);
135     close(fd_);
136   }
137   fd_ = -1;
138 }
139
140 }  // namespace socket
141 }  // namespace pkgmgr_common