• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #undef LOG_DOMAIN
29 #define LOG_DOMAIN 0xD001400
30 
31 #undef LOG_TAG
32 #define LOG_TAG "LocalSocketPair"
33 #define LOGD(fmt, ...) HILOG_DEBUG(LOG_CORE, fmt, ##__VA_ARGS__)
34 #define LOGW(fmt, ...) HILOG_WARN(LOG_CORE, fmt, ##__VA_ARGS__)
35 #define LOGE(fmt, ...) HILOG_ERROR(LOG_CORE, fmt, ##__VA_ARGS__)
36 namespace {
37 constexpr int32_t SOCKET_PAIR_SIZE = 2;
38 constexpr int32_t INVALID_FD = -1;
39 constexpr int32_t ERRNO_EAGAIN = -1;
40 constexpr int32_t ERRNO_OTHER = -2;
41 constexpr int32_t LEAK_FD_CNT = 200;
42 static int32_t g_fdCnt = 0;
43 }  // namespace
44 
LocalSocketPair()45 LocalSocketPair::LocalSocketPair()
46     : sendFd_(INVALID_FD), receiveFd_(INVALID_FD)
47 {
48 }
49 
~LocalSocketPair()50 LocalSocketPair::~LocalSocketPair()
51 {
52     LOGD("%{public}s close socketpair, sendFd : %{public}d, receiveFd : %{public}d", __func__, sendFd_, receiveFd_);
53     if ((sendFd_ != INVALID_FD) || (receiveFd_ != INVALID_FD)) {
54         g_fdCnt--;
55     }
56     CloseFd(sendFd_);
57     CloseFd(receiveFd_);
58 }
59 
SetSockopt(size_t sendSize,size_t receiveSize,int32_t * socketPair,int32_t socketPairSize)60 int32_t LocalSocketPair::SetSockopt(size_t sendSize, size_t receiveSize, int32_t* socketPair, int32_t socketPairSize)
61 {
62     for (int i = 0; i < socketPairSize; ++i) {
63         int32_t ret = setsockopt(socketPair[i], SOL_SOCKET, SO_SNDBUF, &sendSize, sizeof(sendSize));
64         if (ret != 0) {
65             CloseFd(socketPair[0]);
66             CloseFd(socketPair[1]);
67             LOGE("%{public}s setsockopt socketpair %{public}d sendbuffer size failed", __func__, i);
68             return -1;
69         }
70         ret = setsockopt(socketPair[i], SOL_SOCKET, SO_RCVBUF, &receiveSize, sizeof(receiveSize));
71         if (ret != 0) {
72             CloseFd(socketPair[0]);
73             CloseFd(socketPair[1]);
74             LOGE("%{public}s setsockopt socketpair %{public}d receivebuffer size failed", __func__, i);
75             return -1;
76         }
77         ret = fcntl(socketPair[i], F_SETFL, O_NONBLOCK);
78         if (ret != 0) {
79             CloseFd(socketPair[0]);
80             CloseFd(socketPair[1]);
81             LOGE("%{public}s fcntl socketpair %{public}d nonblock failed", __func__, i);
82             return -1;
83         }
84     }
85     return 0;
86 }
87 
CreateChannel(size_t sendSize,size_t receiveSize)88 int32_t LocalSocketPair::CreateChannel(size_t sendSize, size_t receiveSize)
89 {
90     if ((sendFd_ != INVALID_FD) || (receiveFd_ != INVALID_FD)) {
91         LOGD("%{public}s already create socketpair", __func__);
92         return 0;
93     }
94 
95     int32_t socketPair[SOCKET_PAIR_SIZE] = { 0 };
96     if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, socketPair) != 0) {
97         ScopedBytrace func("Create socketpair failed, errno = " + std::to_string(errno));
98         LOGE("%{public}s create socketpair failed", __func__);
99         return -1;
100     }
101     fdsan_exchange_owner_tag(socketPair[0], 0, LOG_DOMAIN);
102     fdsan_exchange_owner_tag(socketPair[1], 0, LOG_DOMAIN);
103     if (socketPair[0] == 0 || socketPair[1] == 0) {
104         int32_t unusedFds[SOCKET_PAIR_SIZE] = {socketPair[0], socketPair[1]};
105         int32_t err = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, socketPair);
106         CloseFd(unusedFds[0]);
107         CloseFd(unusedFds[1]);
108         if (err != 0) {
109             ScopedBytrace func2("Create socketpair failed for the second time, errno = " + std::to_string(errno));
110             LOGE("%{public}s create socketpair failed", __func__);
111             return -1;
112         }
113         fdsan_exchange_owner_tag(socketPair[0], 0, LOG_DOMAIN);
114         fdsan_exchange_owner_tag(socketPair[1], 0, LOG_DOMAIN);
115     }
116 
117     // set socket attr
118     int32_t ret = SetSockopt(sendSize, receiveSize, socketPair, SOCKET_PAIR_SIZE);
119     if (ret != 0) {
120         return ret;
121     }
122     sendFd_ = socketPair[0];
123     receiveFd_ = socketPair[1];
124     if ((sendFd_ <= 0) || (receiveFd_ <= 0)) {
125         LOGE("%{public}s socketpair invalid fd, sendFd_:%{public}d, receiveFd_:%{public}d",
126             __func__, sendFd_, receiveFd_);
127         return -1;
128     }
129     LOGD("%{public}s create socketpair success, receiveFd_ : %{public}d, sendFd_ : %{public}d", __func__, receiveFd_,
130         sendFd_);
131     g_fdCnt++;
132     if (g_fdCnt > LEAK_FD_CNT) {
133         LOGW("%{public}s fdCnt: %{public}d", __func__, g_fdCnt);
134     }
135 
136     return 0;
137 }
138 
SendData(const void * vaddr,size_t size)139 int32_t LocalSocketPair::SendData(const void *vaddr, size_t size)
140 {
141     if (vaddr == nullptr || sendFd_ < 0) {
142         LOGE("%{public}s failed, param is invalid", __func__);
143         return -1;
144     }
145     ssize_t length = TEMP_FAILURE_RETRY(send(sendFd_, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL));
146     if (length <= 0) {
147         int errnoRecord = errno;
148         ScopedBytrace func("SocketPair SendData failed, errno = " + std::to_string(errnoRecord) +
149                             ", sendFd_ = " + std::to_string(sendFd_) + ", receiveFd_ = " + std::to_string(receiveFd_) +
150                             ", length = " + std::to_string(length));
151         if (errnoRecord == EAGAIN) {
152             return ERRNO_EAGAIN;
153         } else {
154             LOGE("%{public}s send failed, errno:%{public}d, length:%{public}d, sendFd:%{public}d, receiveFd:%{public}d",
155                 __func__, errnoRecord, static_cast<int32_t>(length), sendFd_, receiveFd_);
156             return ERRNO_OTHER;
157         }
158     }
159     return length;
160 }
161 
ReceiveData(void * vaddr,size_t size)162 int32_t LocalSocketPair::ReceiveData(void *vaddr, size_t size)
163 {
164     if (vaddr == nullptr || (receiveFd_ < 0)) {
165         LOGE("%{public}s failed, vaddr is null or receiveFd_ invalid", __func__);
166         return -1;
167     }
168     ssize_t length;
169     do {
170         length = recv(receiveFd_, vaddr, size, MSG_DONTWAIT);
171     } while (errno == EINTR);
172     if (length < 0) {
173         ScopedBytrace func("SocketPair ReceiveData failed errno = " + std::to_string(errno) +
174                             ", sendFd_ = " + std::to_string(sendFd_) + ", receiveFd_ = " + std::to_string(receiveFd_) +
175                             ", length = " + std::to_string(length));
176         return -1;
177     }
178     return length;
179 }
180 
181 // internal interface
SendFdToBinder(MessageParcel & data,int32_t & fd)182 int32_t LocalSocketPair::SendFdToBinder(MessageParcel &data, int32_t &fd)
183 {
184     if (fd < 0) {
185         return -1;
186     }
187     // need dup???
188     bool result = data.WriteFileDescriptor(fd);
189     if (!result) {
190         return -1;
191     }
192     return 0;
193 }
194 
SendToBinder(MessageParcel & data)195 int32_t LocalSocketPair::SendToBinder(MessageParcel &data)
196 {
197     return SendFdToBinder(data, sendFd_);
198 }
199 
ReceiveToBinder(MessageParcel & data)200 int32_t LocalSocketPair::ReceiveToBinder(MessageParcel &data)
201 {
202     return SendFdToBinder(data, receiveFd_);
203 }
204 
205 // internal interface
CloseFd(int32_t & fd)206 void LocalSocketPair::CloseFd(int32_t &fd)
207 {
208     if (fd != INVALID_FD) {
209         fdsan_close_with_tag(fd, LOG_DOMAIN);
210         fd = INVALID_FD;
211     }
212 }
213 }
214 
215