1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "local_socketpair.h"
17 #include "hilog/log.h"
18
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <cerrno>
24 #include <scoped_bytrace.h>
25
26 namespace OHOS {
27 using namespace OHOS::HiviewDFX;
28
29 namespace {
30 constexpr HiLogLabel LABEL = { LOG_CORE, 0xD001400, "LocalSocketPair" };
31 constexpr int32_t SOCKET_PAIR_SIZE = 2;
32 constexpr int32_t INVALID_FD = -1;
33 constexpr int32_t ERRNO_EAGAIN = -1;
34 constexpr int32_t ERRNO_OTHER = -2;
35 } // namespace
36
LocalSocketPair()37 LocalSocketPair::LocalSocketPair()
38 : sendFd_(INVALID_FD), receiveFd_(INVALID_FD)
39 {
40 }
41
~LocalSocketPair()42 LocalSocketPair::~LocalSocketPair()
43 {
44 HiLog::Debug(LABEL, "%{public}s close socketpair, sendFd : %{public}d, receiveFd : %{public}d",
45 __func__, sendFd_, receiveFd_);
46 CloseFd(sendFd_);
47 CloseFd(receiveFd_);
48 }
49
CreateChannel(size_t sendSize,size_t receiveSize)50 int32_t LocalSocketPair::CreateChannel(size_t sendSize, size_t receiveSize)
51 {
52 if ((sendFd_ != INVALID_FD) || (receiveFd_ != INVALID_FD)) {
53 HiLog::Debug(LABEL, "%{public}s already create socketpair", __func__);
54 return 0;
55 }
56
57 int32_t socketPair[SOCKET_PAIR_SIZE] = { 0 };
58 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, socketPair) != 0) {
59 ScopedBytrace func("Create socketpair failed, errno = " + std::to_string(errno));
60 HiLog::Error(LABEL, "%{public}s create socketpair failed", __func__);
61 return -1;
62 }
63 if (socketPair[0] == 0 || socketPair[1] == 0) {
64 int32_t unusedFds[SOCKET_PAIR_SIZE] = {socketPair[0], socketPair[1]};
65 int32_t err = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, socketPair);
66 CloseFd(unusedFds[0]);
67 CloseFd(unusedFds[1]);
68 if (err != 0) {
69 ScopedBytrace func2("Create socketpair failed for the second time, errno = " + std::to_string(errno));
70 HiLog::Error(LABEL, "%{public}s create socketpair failed", __func__);
71 return -1;
72 }
73 }
74
75 // set socket attr
76 for (int i = 0; i < SOCKET_PAIR_SIZE; ++i) {
77 int32_t ret = setsockopt(socketPair[i], SOL_SOCKET, SO_SNDBUF, &sendSize, sizeof(sendSize));
78 if (ret != 0) {
79 HiLog::Error(LABEL, "%{public}s setsockopt socketpair %{public}d sendbuffer size failed", __func__, i);
80 return -1;
81 }
82 ret = setsockopt(socketPair[i], SOL_SOCKET, SO_RCVBUF, &receiveSize, sizeof(receiveSize));
83 if (ret != 0) {
84 HiLog::Error(LABEL, "%{public}s setsockopt socketpair %{public}d receivebuffer size failed", __func__, i);
85 return -1;
86 }
87 ret = fcntl(socketPair[i], F_SETFL, O_NONBLOCK);
88 if (ret != 0) {
89 HiLog::Error(LABEL, "%{public}s fcntl socketpair %{public}d nonblock failed", __func__, i);
90 return -1;
91 }
92 }
93 sendFd_ = socketPair[0];
94 receiveFd_ = socketPair[1];
95 HiLog::Debug(LABEL, "%{public}s create socketpair success, receiveFd_ : %{public}d, sendFd_ : %{public}d", __func__,
96 receiveFd_, sendFd_);
97
98 return 0;
99 }
100
SendData(const void * vaddr,size_t size)101 int32_t LocalSocketPair::SendData(const void *vaddr, size_t size)
102 {
103 if (vaddr == nullptr || sendFd_ < 0) {
104 HiLog::Error(LABEL, "%{public}s failed, param is invalid", __func__);
105 return -1;
106 }
107 ssize_t length = TEMP_FAILURE_RETRY(send(sendFd_, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL));
108 if (length < 0) {
109 int errnoRecord = errno;
110 ScopedBytrace func("SocketPair SendData failed, errno = " + std::to_string(errnoRecord) +
111 ", sendFd_ = " + std::to_string(sendFd_) + ", receiveFd_ = " + std::to_string(receiveFd_) +
112 ", length = " + std::to_string(length));
113 HiLog::Debug(LABEL, "%{public}s send failed:%{public}d, length = %{public}d",
114 __func__, errnoRecord, static_cast<int32_t>(length));
115 if (errnoRecord == EAGAIN) {
116 return ERRNO_EAGAIN;
117 } else {
118 return ERRNO_OTHER;
119 }
120 }
121 return length;
122 }
123
ReceiveData(void * vaddr,size_t size)124 int32_t LocalSocketPair::ReceiveData(void *vaddr, size_t size)
125 {
126 if (vaddr == nullptr || (receiveFd_ < 0)) {
127 HiLog::Error(LABEL, "%{public}s failed, vaddr is null or receiveFd_ invalid", __func__);
128 return -1;
129 }
130 ssize_t length;
131 do {
132 length = recv(receiveFd_, vaddr, size, MSG_DONTWAIT);
133 } while (errno == EINTR);
134 if (length < 0) {
135 ScopedBytrace func("SocketPair ReceiveData failed errno = " + std::to_string(errno) +
136 ", sendFd_ = " + std::to_string(sendFd_) + ", receiveFd_ = " + std::to_string(receiveFd_) +
137 ", length = " + std::to_string(length));
138 return -1;
139 }
140 return length;
141 }
142
143 // internal interface
SendFdToBinder(MessageParcel & data,int32_t & fd)144 int32_t LocalSocketPair::SendFdToBinder(MessageParcel &data, int32_t &fd)
145 {
146 if (fd < 0) {
147 return -1;
148 }
149 // need dup???
150 bool result = data.WriteFileDescriptor(fd);
151 if (!result) {
152 return -1;
153 }
154 return 0;
155 }
156
SendToBinder(MessageParcel & data)157 int32_t LocalSocketPair::SendToBinder(MessageParcel &data)
158 {
159 return SendFdToBinder(data, sendFd_);
160 }
161
ReceiveToBinder(MessageParcel & data)162 int32_t LocalSocketPair::ReceiveToBinder(MessageParcel &data)
163 {
164 return SendFdToBinder(data, receiveFd_);
165 }
166
167 // internal interface
CloseFd(int32_t & fd)168 void LocalSocketPair::CloseFd(int32_t &fd)
169 {
170 if (fd != INVALID_FD) {
171 close(fd);
172 fd = INVALID_FD;
173 }
174 }
175 }
176
177