• 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 
25 namespace OHOS {
26 using namespace OHOS::HiviewDFX;
27 
28 namespace {
29 constexpr HiLogLabel LABEL = { LOG_CORE, 0xD001400, "LocalSocketPair" };
30 constexpr int32_t DEFAULT_CHANNEL_SIZE = 2 * 1024;
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     HiLog::Debug(LABEL, "%{public}s sendFd: %{public}d", __func__, sendFd_);
41 }
42 
~LocalSocketPair()43 LocalSocketPair::~LocalSocketPair()
44 {
45     CloseFd(sendFd_);
46     CloseFd(receiveFd_);
47 }
48 
CreateChannel(size_t sendSize,size_t receiveSize)49 int32_t LocalSocketPair::CreateChannel(size_t sendSize, size_t receiveSize)
50 {
51     if ((sendFd_ != INVALID_FD) || (receiveFd_ != INVALID_FD)) {
52         HiLog::Debug(LABEL, "%{public}s already create socketpair", __func__);
53         return 0;
54     }
55 
56     int32_t socketPair[SOCKET_PAIR_SIZE] = { 0 };
57     if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, socketPair) != 0) {
58         HiLog::Error(LABEL, "%{public}s create socketpair failed", __func__);
59         sendFd_ = INVALID_FD;
60         receiveFd_ = INVALID_FD;
61         return -1;
62     }
63 
64     // set socket attr
65     setsockopt(socketPair[0], SOL_SOCKET, SO_SNDBUF, &sendSize, sizeof(sendSize));
66     setsockopt(socketPair[1], SOL_SOCKET, SO_RCVBUF, &receiveSize, sizeof(receiveSize));
67     int32_t bufferSize = DEFAULT_CHANNEL_SIZE;
68     int32_t ret = setsockopt(socketPair[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
69     if (ret != 0) {
70         HiLog::Error(LABEL, "%{public}s setsockopt socketpair 0 failed", __func__);
71         return -1;
72     }
73     ret = setsockopt(socketPair[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
74     if (ret != 0) {
75         HiLog::Error(LABEL, "%{public}s setsockopt socketpair 1 failed", __func__);
76         return -1;
77     }
78     ret = fcntl(socketPair[0], F_SETFL, O_NONBLOCK);
79     if (ret != 0) {
80         HiLog::Error(LABEL, "%{public}s fcntl socketpair 0 failed", __func__);
81         return -1;
82     }
83     ret = fcntl(socketPair[1], F_SETFL, O_NONBLOCK);
84     if (ret != 0) {
85         HiLog::Error(LABEL, "%{public}s fcntl socketpair 1 failed", __func__);
86         return -1;
87     }
88     sendFd_ = socketPair[0];
89     receiveFd_ = socketPair[1];
90     HiLog::Debug(LABEL, "%{public}s create socketpair success, receiveFd_ : %{public}d, sendFd_ : %{public}d", __func__,
91                  receiveFd_, sendFd_);
92 
93     return 0;
94 }
95 
SendData(const void * vaddr,size_t size)96 int32_t LocalSocketPair::SendData(const void *vaddr, size_t size)
97 {
98     if (vaddr == nullptr || sendFd_ < 0) {
99         HiLog::Error(LABEL, "%{public}s failed, param is invalid", __func__);
100         return -1;
101     }
102     ssize_t length;
103     do {
104         length = send(sendFd_, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
105     } while (errno == EINTR);
106     if (length < 0) {
107         HiLog::Error(LABEL, "%{public}s send fail : %{public}d, length = %{public}d", __func__, errno, (int32_t)length);
108         if (errno == EAGAIN) {
109             return ERRNO_EAGAIN;
110         } else {
111             return ERRNO_OTHER;
112         }
113     }
114     return length;
115 }
116 
ReceiveData(void * vaddr,size_t size)117 int32_t LocalSocketPair::ReceiveData(void *vaddr, size_t size)
118 {
119     if (vaddr == nullptr || (receiveFd_ < 0)) {
120         HiLog::Error(LABEL, "%{public}s failed, vaddr is null or receiveFd_ invalid", __func__);
121         return -1;
122     }
123     ssize_t length;
124     do {
125         length = recv(receiveFd_, vaddr, size, MSG_DONTWAIT);
126     } while (errno == EINTR);
127     if (length < 0) {
128         return -1;
129     }
130     return length;
131 }
132 
133 // internal interface
SendFdToBinder(MessageParcel & data,int32_t & fd)134 int32_t LocalSocketPair::SendFdToBinder(MessageParcel &data, int32_t &fd)
135 {
136     if (fd < 0) {
137         return -1;
138     }
139     // need dup???
140     bool result = data.WriteFileDescriptor(fd);
141     if (!result) {
142         return -1;
143     }
144     return 0;
145 }
146 
SendToBinder(MessageParcel & data)147 int32_t LocalSocketPair::SendToBinder(MessageParcel &data)
148 {
149     return SendFdToBinder(data, sendFd_);
150 }
151 
ReceiveToBinder(MessageParcel & data)152 int32_t LocalSocketPair::ReceiveToBinder(MessageParcel &data)
153 {
154     return SendFdToBinder(data, receiveFd_);
155 }
156 
157 // internal interface
CloseFd(int32_t & fd)158 void LocalSocketPair::CloseFd(int32_t &fd)
159 {
160     if (fd != INVALID_FD) {
161         close(fd);
162         fd = INVALID_FD;
163     }
164 }
165 }
166 
167