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