• 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 "softbus_socket.h"
17 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <securec.h>
21 
22 #include "softbus_adapter_errcode.h"
23 #include "softbus_adapter_socket.h"
24 #include "softbus_def.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         CLOGE("Bad socket interface!");
42         return SOFTBUS_ERR;
43     }
44     int ret = SoftBusMutexLock(&g_socketsMutex);
45     if (ret != SOFTBUS_OK) {
46         CLOGE("get lock failed!ret=%" PRId32, 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         CLOGE("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         CLOGE("get lock failed!ret=%" PRId32, 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     CLOGI("newip not deployed");
86     return SOFTBUS_OK;
87 }
88 
ConnInitSockets(void)89 NO_SANITIZE("cfi") int32_t ConnInitSockets(void)
90 {
91     int32_t ret = SoftBusMutexInit(&g_socketsMutex, NULL);
92     if (ret != SOFTBUS_OK) {
93         CLOGE("init mutex failed!ret=%" PRId32, 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         CLOGE("regist tcp failed!!ret=%" PRId32, ret);
102         (void)SoftBusMutexDestroy(&g_socketsMutex);
103         return ret;
104     }
105     CLOGI("tcp registed!");
106 
107     ret = RegistNewIpSocket();
108     if (ret != SOFTBUS_OK) {
109         CLOGE("regist newip failed!!ret=%" PRId32, ret);
110         (void)SoftBusMutexDestroy(&g_socketsMutex);
111         return ret;
112     }
113 
114     return ret;
115 }
116 
ConnDeinitSockets(void)117 NO_SANITIZE("cfi") 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 NO_SANITIZE("cfi") 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         ALOGE("protocol not supported!protocol=%d", option->socketOption.protocol);
131         return SOFTBUS_ERR;
132     }
133     return socketInterface->OpenClientSocket(option, bindAddr, isNonBlock);
134 }
135 
WaitEvent(int fd,short events,int timeout)136 static int WaitEvent(int fd, short events, int timeout)
137 {
138     if (fd < 0) {
139         CLOGE("fd=%d invalid params", fd);
140         return -1;
141     }
142     SoftBusSockTimeOut tv = { 0 };
143     tv.sec = 0;
144     tv.usec = timeout;
145     int rc = 0;
146     switch (events) {
147         case SOFTBUS_SOCKET_OUT: {
148             SoftBusFdSet writeSet;
149             SoftBusSocketFdZero(&writeSet);
150             SoftBusSocketFdSet(fd, &writeSet);
151             rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketSelect(fd + 1, NULL, &writeSet, NULL, &tv));
152             if (rc < 0) {
153                 break;
154             }
155             if (!SoftBusSocketFdIsset(fd, &writeSet)) {
156                 rc = 0;
157             }
158             break;
159         }
160         case SOFTBUS_SOCKET_IN: {
161             SoftBusFdSet readSet;
162             SoftBusSocketFdZero(&readSet);
163             SoftBusSocketFdSet(fd, &readSet);
164             rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketSelect(fd + 1, &readSet, NULL, NULL, &tv));
165             if (rc < 0) {
166                 break;
167             }
168             if (!SoftBusSocketFdIsset(fd, &readSet)) {
169                 rc = 0;
170             }
171             break;
172         }
173         default:
174             break;
175     }
176     return rc;
177 }
ConnToggleNonBlockMode(int32_t fd,bool isNonBlock)178 NO_SANITIZE("cfi") int32_t ConnToggleNonBlockMode(int32_t fd, bool isNonBlock)
179 {
180     if (fd < 0) {
181         return SOFTBUS_INVALID_PARAM;
182     }
183     int32_t flags = fcntl(fd, F_GETFL, 0);
184     if (flags < 0) {
185         CLOGE("fd=%d,fcntl get flag failed, errno=%d", fd, errno);
186         return SOFTBUS_ERR;
187     }
188     if (isNonBlock && ((uint32_t)flags & O_NONBLOCK) == 0) {
189         flags = (int32_t)((uint32_t)flags | O_NONBLOCK);
190         CLOGI("fd=%d set to nonblock", fd);
191     } else if (!isNonBlock && ((uint32_t)flags & O_NONBLOCK) != 0) {
192         flags = (int32_t)((uint32_t)flags & ~O_NONBLOCK);
193         CLOGI("fd=%d set to block", fd);
194     } else {
195         CLOGI("fd=%d nonblock state is already ok", fd);
196         return SOFTBUS_OK;
197     }
198     return fcntl(fd, F_SETFL, flags);
199 }
200 
ConnSendSocketData(int32_t fd,const char * buf,size_t len,int32_t timeout)201 NO_SANITIZE("cfi") ssize_t ConnSendSocketData(int32_t fd, const char *buf, size_t len, int32_t timeout)
202 {
203     if (fd < 0 || buf == NULL || len == 0) {
204         CLOGE("fd=%d invalid params", fd);
205         return -1;
206     }
207 
208     if (timeout == 0) {
209         timeout = USER_TIMEOUT_MS;
210     }
211 
212     int err = WaitEvent(fd, SOFTBUS_SOCKET_OUT, USER_TIMEOUT_MS);
213     if (err <= 0) {
214         CLOGE("wait event error %d", err);
215         return err;
216     }
217     ssize_t bytes = 0;
218     while (1) {
219         ssize_t rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketSend(fd, &buf[bytes], len - bytes, 0));
220         if (rc == SOFTBUS_ADAPTER_SOCKET_EAGAIN) {
221             continue;
222         } else if (rc <= 0) {
223             if (bytes == 0) {
224                 bytes = -1;
225             }
226             CLOGE("tcp send fail %zd %d", rc, errno);
227             break;
228         }
229         bytes += rc;
230         if (bytes == (ssize_t)(len)) {
231             break;
232         }
233 
234         err = WaitEvent(fd, SOFTBUS_SOCKET_OUT, timeout);
235         if (err == 0) {
236             continue;
237         } else if (err < 0) {
238             if (bytes == 0) {
239                 CLOGE("send data wait event fail %d", err);
240                 bytes = err;
241             }
242             break;
243         }
244     }
245     return bytes;
246 }
247 
OnRecvData(int32_t fd,char * buf,size_t len,int timeout,int flags)248 static ssize_t OnRecvData(int32_t fd, char *buf, size_t len, int timeout, int flags)
249 {
250     if (fd < 0 || buf == NULL || len == 0) {
251         CLOGE("fd[%d] len[%zu] invalid params", fd, len);
252         return -1;
253     }
254 
255     if (timeout != 0) {
256         int err = WaitEvent(fd, SOFTBUS_SOCKET_IN, timeout);
257         if (err < 0) {
258             CLOGE("recv data wait event err[%d]", err);
259             return err;
260         }
261     }
262 
263     ssize_t rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketRecv(fd, buf, len, flags));
264     if (rc == SOFTBUS_ADAPTER_SOCKET_EAGAIN) {
265         CLOGW("recv data socket EAGAIN");
266         rc = 0;
267     } else if (rc == 0) {
268         CLOGW("recv data fail, peer close connection, fd=%d", fd);
269         rc = -1;
270     } else if (rc < 0) {
271         CLOGE("recv data fail fd[%d] errno[%d], rc[%d]", fd, errno, rc);
272         rc = -1;
273     }
274     return rc;
275 }
276 
ConnRecvSocketData(int32_t fd,char * buf,size_t len,int32_t timeout)277 NO_SANITIZE("cfi") ssize_t ConnRecvSocketData(int32_t fd, char *buf, size_t len, int32_t timeout)
278 {
279     return OnRecvData(fd, buf, len, timeout, 0);
280 }
281 
ConnCloseSocket(int32_t fd)282 NO_SANITIZE("cfi") void ConnCloseSocket(int32_t fd)
283 {
284     if (fd >= 0) {
285         CLOGI("close fd=%d", fd);
286         SoftBusSocketClose(fd);
287     }
288 }
289 
ConnShutdownSocket(int32_t fd)290 NO_SANITIZE("cfi") void ConnShutdownSocket(int32_t fd)
291 {
292     if (fd >= 0) {
293         CLOGI("shutdown fd=%d", fd);
294         SoftBusSocketShutDown(fd, SOFTBUS_SHUT_RDWR);
295         SoftBusSocketClose(fd);
296     }
297 }
298 
ConnGetSocketError(int32_t fd)299 NO_SANITIZE("cfi") int32_t ConnGetSocketError(int32_t fd)
300 {
301     return SoftBusSocketGetError(fd);
302 }
303 
ConnGetLocalSocketPort(int32_t fd)304 NO_SANITIZE("cfi") int32_t ConnGetLocalSocketPort(int32_t fd)
305 {
306     const SocketInterface *socketInterface = GetSocketInterface(LNN_PROTOCOL_IP);
307     if (socketInterface == NULL) {
308         CLOGW("LNN_PROTOCOL_IP not supported!");
309         return SOFTBUS_ERR;
310     }
311     return socketInterface->GetSockPort(fd);
312 }
313 
ConnGetPeerSocketAddr(int32_t fd,SocketAddr * socketAddr)314 NO_SANITIZE("cfi") int32_t ConnGetPeerSocketAddr(int32_t fd, SocketAddr *socketAddr)
315 {
316     SoftBusSockAddrIn addr;
317     int32_t addrLen = (int32_t)sizeof(addr);
318     if (socketAddr == NULL) {
319         CLOGE("invalid param");
320         return SOFTBUS_INVALID_PARAM;
321     }
322     int rc = SoftBusSocketGetPeerName(fd, (SoftBusSockAddr *)&addr, &addrLen);
323     if (rc != 0) {
324         CLOGE("fd=%d, GetPeerName rc=%d", fd, rc);
325         return SOFTBUS_ERR;
326     }
327     if (SoftBusInetNtoP(SOFTBUS_AF_INET, (void *)&addr.sinAddr, socketAddr->addr, sizeof(socketAddr->addr)) == NULL) {
328         CLOGE("fd=%d, InetNtoP fail", fd);
329         return SOFTBUS_ERR;
330     }
331     socketAddr->port = SoftBusNtoHs(addr.sinPort);
332     return SOFTBUS_OK;
333 }
334