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 "softbus_socket.h"
17
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <securec.h>
21 #include <unistd.h>
22
23 #include "softbus_adapter_errcode.h"
24 #include "softbus_adapter_socket.h"
25 #include "softbus_errcode.h"
26 #include "softbus_log.h"
27 #include "softbus_tcp_socket.h"
28
29 #define MAX_SOCKET_TYPE 5
30 #define SEND_BUF_SIZE 0x200000 // 2M
31 #define RECV_BUF_SIZE 0x100000 // 1M
32 #define USER_TIMEOUT_MS 500000 // 500000us
33
34 static const SocketInterface *g_socketInterfaces[MAX_SOCKET_TYPE] = {0};
35 static SoftBusMutex g_socketsMutex;
36
RegistSocketProtocol(const SocketInterface * interface)37 int32_t RegistSocketProtocol(const SocketInterface *interface)
38 {
39 if (interface == NULL || interface->GetSockPort == NULL || interface->OpenClientSocket == NULL ||
40 interface->OpenServerSocket == NULL || interface->AcceptClient == NULL) {
41 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "Bad socket interface!");
42 return SOFTBUS_ERR;
43 }
44 int ret = SoftBusMutexLock(&g_socketsMutex);
45 if (ret != SOFTBUS_OK) {
46 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:get lock failed!ret=%" PRId32, __func__, ret);
47 return ret;
48 }
49
50 ret = SOFTBUS_ERR;
51 for (uint8_t i = 0; i < MAX_SOCKET_TYPE; i++) {
52 if (g_socketInterfaces[i] == NULL) {
53 g_socketInterfaces[i] = interface;
54 ret = SOFTBUS_OK;
55 break;
56 }
57 }
58 (void)SoftBusMutexUnlock(&g_socketsMutex);
59 if (ret != SOFTBUS_OK) {
60 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "socket type list is full!");
61 }
62 return ret;
63 }
64
GetSocketInterface(ProtocolType protocolType)65 const SocketInterface *GetSocketInterface(ProtocolType protocolType)
66 {
67 int ret = SoftBusMutexLock(&g_socketsMutex);
68 if (ret != SOFTBUS_OK) {
69 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:get lock failed!ret=%" PRId32, __func__, ret);
70 return NULL;
71 }
72 const SocketInterface *result = NULL;
73 for (uint8_t i = 0; i < MAX_SOCKET_TYPE; i++) {
74 if (g_socketInterfaces[i] != NULL && g_socketInterfaces[i]->type == protocolType) {
75 result = g_socketInterfaces[i];
76 break;
77 }
78 }
79 (void)SoftBusMutexUnlock(&g_socketsMutex);
80 return result;
81 }
82
RegistNewIpSocket(void)83 int32_t __attribute__ ((weak)) RegistNewIpSocket(void)
84 {
85 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_INFO, "%s: newip not deployed", __func__);
86 return SOFTBUS_OK;
87 }
88
ConnInitSockets(void)89 int32_t ConnInitSockets(void)
90 {
91 int32_t ret = SoftBusMutexInit(&g_socketsMutex, NULL);
92 if (ret != SOFTBUS_OK) {
93 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s: init mutex failed!ret=%" PRId32, __func__, ret);
94 return ret;
95 }
96
97 (void)memset_s(g_socketInterfaces, sizeof(g_socketInterfaces), 0, sizeof(g_socketInterfaces));
98
99 ret = RegistSocketProtocol(GetTcpProtocol());
100 if (ret != SOFTBUS_OK) {
101 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s: regist tcp failed!!ret=%" PRId32, __func__, ret);
102 (void)SoftBusMutexDestroy(&g_socketsMutex);
103 return ret;
104 }
105 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_INFO, "%s: tcp registed!", __func__);
106
107 ret = RegistNewIpSocket();
108 if (ret != SOFTBUS_OK) {
109 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s: regist newip failed!!ret=%" PRId32, __func__, ret);
110 (void)SoftBusMutexDestroy(&g_socketsMutex);
111 return ret;
112 }
113
114 return ret;
115 }
116
ConnDeinitSockets(void)117 void ConnDeinitSockets(void)
118 {
119 (void)memset_s(g_socketInterfaces, sizeof(g_socketInterfaces), 0, sizeof(g_socketInterfaces));
120 (void)SoftBusMutexDestroy(&g_socketsMutex);
121 }
122
ConnOpenClientSocket(const ConnectOption * option,const char * bindAddr,bool isNonBlock)123 int32_t ConnOpenClientSocket(const ConnectOption *option, const char *bindAddr, bool isNonBlock)
124 {
125 if (option == NULL || bindAddr == NULL) {
126 return SOFTBUS_ERR;
127 }
128 const SocketInterface *socketInterface = GetSocketInterface(option->socketOption.protocol);
129 if (socketInterface == NULL) {
130 SoftBusLog(
131 SOFTBUS_LOG_AUTH, SOFTBUS_LOG_ERROR, "protocol not supported!protocol=%d", option->socketOption.protocol);
132 return SOFTBUS_ERR;
133 }
134 return socketInterface->OpenClientSocket(option, bindAddr, isNonBlock);
135 }
136
WaitEvent(int fd,short events,int timeout)137 static int WaitEvent(int fd, short events, int timeout)
138 {
139 if (fd < 0) {
140 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:%d:fd=%d invalid params", __func__, __LINE__, fd);
141 return -1;
142 }
143 SoftBusSockTimeOut tv = {0};
144 tv.sec = 0;
145 tv.usec = timeout;
146 int rc = 0;
147 switch (events) {
148 case SOFTBUS_SOCKET_OUT: {
149 SoftBusFdSet writeSet;
150 SoftBusSocketFdZero(&writeSet);
151 SoftBusSocketFdSet(fd, &writeSet);
152 rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketSelect(fd + 1, NULL, &writeSet, NULL, &tv));
153 if (rc < 0) {
154 break;
155 }
156 if (!SoftBusSocketFdIsset(fd, &writeSet)) {
157 rc = 0;
158 }
159 break;
160 }
161 case SOFTBUS_SOCKET_IN: {
162 SoftBusFdSet readSet;
163 SoftBusSocketFdZero(&readSet);
164 SoftBusSocketFdSet(fd, &readSet);
165 rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketSelect(fd + 1, &readSet, NULL, NULL, &tv));
166 if (rc < 0) {
167 break;
168 }
169 if (!SoftBusSocketFdIsset(fd, &readSet)) {
170 rc = 0;
171 }
172 break;
173 }
174 default:
175 break;
176 }
177 return rc;
178 }
ConnToggleNonBlockMode(int32_t fd,bool isNonBlock)179 int32_t ConnToggleNonBlockMode(int32_t fd, bool isNonBlock)
180 {
181 if (fd < 0) {
182 return SOFTBUS_INVALID_PARAM;
183 }
184 int32_t flags = fcntl(fd, F_GETFL, 0);
185 if (flags < 0) {
186 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "fd=%d,fcntl get flag failed, errno=%d", fd, errno);
187 return SOFTBUS_ERR;
188 }
189 if (isNonBlock && ((uint32_t)flags & O_NONBLOCK) == 0) {
190 flags = (int32_t)((uint32_t)flags | O_NONBLOCK);
191 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_INFO, "fd=%d set to nonblock", fd);
192 } else if (!isNonBlock && ((uint32_t)flags & O_NONBLOCK) != 0) {
193 flags = (int32_t)((uint32_t)flags & ~O_NONBLOCK);
194 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_INFO, "fd=%d set to block", fd);
195 } else {
196 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_INFO, "fd=%d nonblock state is already ok", fd);
197 return SOFTBUS_OK;
198 }
199 return fcntl(fd, F_SETFL, flags);
200 }
201
ConnSendSocketData(int32_t fd,const char * buf,size_t len,int32_t timeout)202 ssize_t ConnSendSocketData(int32_t fd, const char *buf, size_t len, int32_t timeout)
203 {
204 if (fd < 0 || buf == NULL || len == 0) {
205 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "fd=%d invalid params", fd);
206 return -1;
207 }
208
209 if (timeout == 0) {
210 timeout = USER_TIMEOUT_MS;
211 }
212
213 int err = WaitEvent(fd, SOFTBUS_SOCKET_OUT, USER_TIMEOUT_MS);
214 if (err <= 0) {
215 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "wait event error %d", err);
216 return err;
217 }
218 ssize_t bytes = 0;
219 while (1) {
220 ssize_t rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketSend(fd, &buf[bytes], len - bytes, 0));
221 if (rc == SOFTBUS_ADAPTER_SOCKET_EAGAIN) {
222 continue;
223 } else if (rc <= 0) {
224 if (bytes == 0) {
225 bytes = -1;
226 }
227 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "tcp send fail %zd %d", rc, errno);
228 break;
229 }
230 bytes += rc;
231 if (bytes == (ssize_t)(len)) {
232 break;
233 }
234
235 err = WaitEvent(fd, SOFTBUS_SOCKET_OUT, timeout);
236 if (err == 0) {
237 continue;
238 } else if (err < 0) {
239 if (bytes == 0) {
240 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "send data wait event fail %d", err);
241 bytes = err;
242 }
243 break;
244 }
245 }
246 return bytes;
247 }
248
OnRecvData(int32_t fd,char * buf,size_t len,int timeout,int flags)249 static ssize_t OnRecvData(int32_t fd, char *buf, size_t len, int timeout, int flags)
250 {
251 if (fd < 0 || buf == NULL || len == 0) {
252 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "fd[%d] len[%zu] invalid params", fd, len);
253 return -1;
254 }
255
256 if (timeout != 0) {
257 int err = WaitEvent(fd, SOFTBUS_SOCKET_IN, timeout);
258 if (err < 0) {
259 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "recv data wait event err[%d]", err);
260 return err;
261 }
262 }
263
264 ssize_t rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketRecv(fd, buf, len, flags));
265 if (rc == SOFTBUS_ADAPTER_SOCKET_EAGAIN) {
266 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_WARN, "recv data socket EAGAIN");
267 rc = 0;
268 } else if (rc <= 0) {
269 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "recv data fail errno[%d], rc[%d]", errno, rc);
270 rc = -1;
271 }
272 return rc;
273 }
274
ConnRecvSocketData(int32_t fd,char * buf,size_t len,int32_t timeout)275 ssize_t ConnRecvSocketData(int32_t fd, char *buf, size_t len, int32_t timeout)
276 {
277 return OnRecvData(fd, buf, len, timeout, 0);
278 }
279
ConnCloseSocket(int32_t fd)280 void ConnCloseSocket(int32_t fd)
281 {
282 if (fd >= 0) {
283 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_INFO, "close fd=%d", fd);
284 SoftBusSocketClose(fd);
285 }
286 }
287
ConnShutdownSocket(int32_t fd)288 void ConnShutdownSocket(int32_t fd)
289 {
290 if (fd >= 0) {
291 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_INFO, "shutdown fd=%d", fd);
292 SoftBusSocketShutDown(fd, SOFTBUS_SHUT_RDWR);
293 SoftBusSocketClose(fd);
294 }
295 }
296
ConnGetSocketError(int32_t fd)297 int32_t ConnGetSocketError(int32_t fd)
298 {
299 return SoftBusSocketGetError(fd);
300 }
301
ConnGetLocalSocketPort(int32_t fd)302 int32_t ConnGetLocalSocketPort(int32_t fd)
303 {
304 const SocketInterface *socketInterface = GetSocketInterface(LNN_PROTOCOL_IP);
305 if (socketInterface == NULL) {
306 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_WARN, "LNN_PROTOCOL_IP not supported!");
307 return SOFTBUS_ERR;
308 }
309 return socketInterface->GetSockPort(fd);
310 }
311
ConnGetPeerSocketAddr(int32_t fd,SocketAddr * socketAddr)312 int32_t ConnGetPeerSocketAddr(int32_t fd, SocketAddr *socketAddr)
313 {
314 SoftBusSockAddrIn addr;
315 int32_t addrLen = (int32_t)sizeof(addr);
316 if (socketAddr == NULL) {
317 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:invalid param", __func__);
318 return SOFTBUS_INVALID_PARAM;
319 }
320 int rc = SoftBusSocketGetPeerName(fd, (SoftBusSockAddr *)&addr, &addrLen);
321 if (rc != 0) {
322 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "fd=%d, GetPeerName rc=%d", fd, rc);
323 return SOFTBUS_ERR;
324 }
325 if (SoftBusInetNtoP(SOFTBUS_AF_INET, (void *)&addr.sinAddr, socketAddr->addr, sizeof(socketAddr->addr)) == NULL) {
326 SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "fd=%d, InetNtoP fail", fd);
327 return SOFTBUS_ERR;
328 }
329 socketAddr->port = SoftBusNtoHs(addr.sinPort);
330 return SOFTBUS_OK;
331 }
332