b730cc124205d7f3807cbd80cb13786a97a0501d
[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 "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() { Destroy(); }
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)", fd_);
64       return -ECOMM;
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)", fd_);
71           return -EAGAIN;
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 void AbstractSocket::SetOption() {
93   int size = 2048;
94   int ret = setsockopt(fd_, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
95   if (ret < 0) {
96     LOGE("setsockopt() is failed. fd(%d), errno(%d)", fd_, errno);
97     return;
98   }
99
100   ret = setsockopt(fd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
101   if (ret < 0) LOGE("setsockopt() is failed. fd(%d), errno(%d)", fd_, errno);
102 }
103
104 int AbstractSocket::Create() {
105   fd_ = ::socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
106   if (fd_ < 0) {
107     LOGE("socket() is failed. errno(%d)", errno);
108     return fd_;
109   }
110
111   addr_.sun_family = AF_UNIX;
112   snprintf(addr_.sun_path, sizeof(addr_.sun_path), "%s", path_.c_str());
113   return 0;
114 }
115
116 void AbstractSocket::Destroy() {
117   if (fd_ > 0) close(fd_);
118 }
119
120 }  // namespace socket
121 }  // namespace pkgmgr_common