• 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 #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