• 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_tcp_socket.h"
17 #include <fcntl.h>
18 #include <securec.h>
19 #include <unistd.h>
20 
21 #include "softbus_adapter_errcode.h"
22 #include "softbus_adapter_socket.h"
23 #include "softbus_errcode.h"
24 #include "softbus_log.h"
25 #include "softbus_socket.h"
26 
27 #define SEND_BUF_SIZE 0x200000  // 2M
28 #define RECV_BUF_SIZE 0x100000  // 1M
29 #define USER_TIMEOUT_MS 500000  // 500000us
30 
31 #ifndef __LITEOS_M__
SetReusePort(int fd,int on)32 static int SetReusePort(int fd, int on)
33 {
34     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_REUSEPORT, &on, sizeof(on));
35     if (rc != 0) {
36         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set SO_REUSEPORT");
37         return -1;
38     }
39     return 0;
40 }
41 #endif
42 
SetReuseAddr(int fd,int on)43 static int SetReuseAddr(int fd, int on)
44 {
45     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_REUSEADDR, &on, sizeof(on));
46     if (rc != 0) {
47         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set SO_REUSEADDR");
48         return -1;
49     }
50     return 0;
51 }
52 
SetNoDelay(int fd,int on)53 static int SetNoDelay(int fd, int on)
54 {
55     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_NODELAY, &on, sizeof(on));
56     if (rc != 0) {
57         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set TCP_NODELAY");
58         return -1;
59     }
60     return 0;
61 }
62 
SetServerOption(int fd)63 static void SetServerOption(int fd)
64 {
65     (void)SetReuseAddr(fd, 1);
66     (void)SetNoDelay(fd, 1);
67 #ifndef __LITEOS_M__
68     (void)SetReusePort(fd, 1);
69 #endif
70 }
71 
SetClientOption(int fd)72 static void SetClientOption(int fd)
73 {
74     SetReuseAddr(fd, 1);
75     SetNoDelay(fd, 1);
76 #ifndef __LITEOS_M__
77     SetReusePort(fd, 1);
78 #endif
79 }
80 
81 
BindLocalIP(int fd,const char * localIP,uint16_t port)82 static int BindLocalIP(int fd, const char *localIP, uint16_t port)
83 {
84     SoftBusSockAddrIn addr;
85 
86     if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) {
87         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "memset failed");
88     }
89 
90     addr.sinFamily = SOFTBUS_AF_INET;
91     int rc = SoftBusInetPtoN(SOFTBUS_AF_INET, localIP, &addr.sinAddr);
92     if (rc != SOFTBUS_ADAPTER_OK) {
93         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "SoftBusInetPtoN rc=%d", rc);
94         return SOFTBUS_ERR;
95     }
96     addr.sinPort = SoftBusHtoNs(port);
97     rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketBind(fd, (SoftBusSockAddr *)&addr, sizeof(addr)));
98     if (rc < 0) {
99         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "bind fd=%d,rc=%d", fd, rc);
100         return SOFTBUS_ERR;
101     }
102     return SOFTBUS_OK;
103 }
104 
SetIpTos(int fd,uint32_t tos)105 int32_t SetIpTos(int fd, uint32_t tos)
106 {
107     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_IP, SOFTBUS_IP_TOS, &tos, sizeof(tos));
108     if (rc != 0) {
109         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set tos failed");
110         return SOFTBUS_TCP_SOCKET_ERR;
111     }
112     return SOFTBUS_OK;
113 }
114 
OpenTcpServerSocket(const LocalListenerInfo * option)115 static int32_t OpenTcpServerSocket(const LocalListenerInfo *option)
116 {
117     if (option == NULL) {
118         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:null ptr!", __func__);
119         return -1;
120     }
121     if (option->type != CONNECT_TCP && option->type != CONNECT_P2P) {
122         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:bad type!type=%d", __func__, option->type);
123         return -1;
124     }
125     if (option->socketOption.port < 0) {
126         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:bad port!port=%d", __func__, option->socketOption.port);
127         return -1;
128     }
129 
130     int fd;
131     int ret = SoftBusSocketCreate(
132         SOFTBUS_AF_INET, SOFTBUS_SOCK_STREAM | SOFTBUS_SOCK_CLOEXEC | SOFTBUS_SOCK_NONBLOCK, 0, (int32_t *)&fd);
133     if (ret != SOFTBUS_OK) {
134         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:Create socket failed! ret=%d", __func__, ret);
135         return -1;
136     }
137 
138     SetServerOption(fd);
139     ret = BindLocalIP(fd, option->socketOption.addr, (uint16_t)option->socketOption.port);
140     if (ret != SOFTBUS_OK) {
141         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "BindLocalIP ret=%d", ret);
142         ConnShutdownSocket(fd);
143         return -1;
144     }
145     return fd;
146 }
147 
BindTcpClientAddr(int fd,const char * inputAddr)148 static int32_t BindTcpClientAddr(int fd, const char *inputAddr)
149 {
150     if (inputAddr == NULL) {
151         return SOFTBUS_OK;
152     }
153 
154     const char *bindAddr = NULL;
155     if (strcmp(inputAddr, BIND_ADDR_ALL) == 0) {
156         bindAddr = "0.0.0.0";
157     } else {
158         SoftBusLog(SOFTBUS_LOG_AUTH, SOFTBUS_LOG_ERROR, "%s:using specified bind addr", __func__);
159         bindAddr = inputAddr;
160     }
161     return BindLocalIP(fd, bindAddr, 0);
162 }
163 
OpenTcpClientSocket(const ConnectOption * option,const char * myIp,bool isNonBlock)164 static int32_t OpenTcpClientSocket(const ConnectOption *option, const char *myIp, bool isNonBlock)
165 {
166     if (option == NULL) {
167         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:null ptr!", __func__);
168         return -1;
169     }
170     if (option->type != CONNECT_TCP && option->type != CONNECT_P2P) {
171         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:bad type!type=%d", __func__, option->type);
172         return -1;
173     }
174     if (option->socketOption.port <= 0) {
175         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "OpenTcpClientSocket invalid para, port=%d",
176             option->socketOption.port);
177         return -1;
178     }
179 
180     int32_t fd = -1;
181     int32_t ret = SoftBusSocketCreate(SOFTBUS_AF_INET, SOFTBUS_SOCK_STREAM, 0, &fd);
182     if (ret != SOFTBUS_OK) {
183         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:%d:fd=%d", __func__, __LINE__, fd);
184         return -1;
185     }
186 
187     if (isNonBlock && ConnToggleNonBlockMode(fd, true) != SOFTBUS_OK) {
188         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set nonblock failed, fd=%d", fd);
189         SoftBusSocketClose(fd);
190         return -1;
191     }
192 
193     SetClientOption(fd);
194     ret = BindTcpClientAddr(fd, myIp);
195     if (ret != SOFTBUS_OK) {
196         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "BindLocalIP ret=%d", ret);
197         ConnShutdownSocket(fd);
198         return -1;
199     }
200     SoftBusSockAddrIn addr;
201     if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) {
202         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "memset failed");
203     }
204     addr.sinFamily = SOFTBUS_AF_INET;
205     SoftBusInetPtoN(SOFTBUS_AF_INET, option->socketOption.addr, &addr.sinAddr);
206     addr.sinPort = SoftBusHtoNs((uint16_t)option->socketOption.port);
207     int rc = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketConnect(fd, (SoftBusSockAddr *)&addr, sizeof(addr)));
208     if ((rc != SOFTBUS_ADAPTER_OK) && (rc != SOFTBUS_ADAPTER_SOCKET_EINPROGRESS) &&
209         (rc != SOFTBUS_ADAPTER_SOCKET_EAGAIN)) {
210         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "fd=%d,connect rc=%d", fd, rc);
211         ConnShutdownSocket(fd);
212         return -1;
213     }
214     return fd;
215 }
216 
GetTcpSockPort(int32_t fd)217 static int32_t GetTcpSockPort(int32_t fd)
218 {
219     SoftBusSockAddrIn addr;
220     int32_t addrLen = sizeof(addr);
221 
222     int rc = SoftBusSocketGetLocalName(fd, (SoftBusSockAddr *)&addr, &addrLen);
223     if (rc != 0) {
224         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "fd=%d,GetTcpSockPort rc=%d", fd, rc);
225         return rc;
226     }
227     return SoftBusNtoHs(addr.sinPort);
228 }
229 
ConnSetTcpKeepAlive(int32_t fd,int32_t seconds)230 int32_t ConnSetTcpKeepAlive(int32_t fd, int32_t seconds)
231 {
232 #define KEEP_ALIVE_COUNT 5
233     if (fd < 0) {
234         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "ConnSetTcpKeepAlive invalid param");
235         return -1;
236     }
237 
238     int32_t rc;
239     int32_t enable;
240     if (seconds > 0) {
241         enable = 1;
242         rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_KEEPIDLE, &seconds, sizeof(seconds));
243         if (rc != 0) {
244             SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set TCP_KEEPIDLE");
245             return -1;
246         }
247 
248         int32_t keepAliveCnt = KEEP_ALIVE_COUNT;
249         rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_KEEPCNT, &keepAliveCnt, sizeof(keepAliveCnt));
250         if (rc != 0) {
251             SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set TCP_KEEPCNT");
252             return -1;
253         }
254 
255         int32_t keepAliveIntvl = 1;
256         rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_KEEPINTVL, &keepAliveIntvl,
257             sizeof(keepAliveIntvl));
258         if (rc != 0) {
259             SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set TCP_KEEPINTVL");
260             return -1;
261         }
262     } else {
263         enable = 0;
264     }
265 
266     rc = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_KEEPALIVE, &enable, sizeof(enable));
267     if (rc != 0) {
268         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set SO_KEEPALIVE");
269         return -1;
270     }
271     return 0;
272 }
273 
274 #ifdef TCP_USER_TIMEOUT
ConnSetTcpUserTimeOut(int32_t fd,uint32_t millSec)275 int32_t ConnSetTcpUserTimeOut(int32_t fd, uint32_t millSec)
276 {
277     if (fd < 0) {
278         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "ConnSetTcpUserTimeOut invalid param");
279         return -1;
280     }
281     if (SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_USER_TIMEOUT, &millSec, sizeof(millSec)) != 0) {
282         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "set SOFTBUS_TCP_USER_TIMEOUT failed");
283         return -1;
284     }
285     return 0;
286 }
287 #else
ConnSetTcpUserTimeOut(int32_t fd,uint32_t millSec)288 int32_t ConnSetTcpUserTimeOut(int32_t fd, uint32_t millSec)
289 {
290     (void)fd;
291     (void)millSec;
292     return 0;
293 }
294 
295 #endif
AcceptTcpClient(int32_t fd,ConnectOption * clientAddr,int32_t * cfd)296 static int32_t AcceptTcpClient(int32_t fd, ConnectOption *clientAddr, int32_t *cfd)
297 {
298     SoftBusSockAddrIn addr;
299     if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) {
300         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "%s:memset failed", __func__);
301         return SOFTBUS_MEM_ERR;
302     }
303     uint32_t addrLen = sizeof(addr);
304     int32_t ret =
305         SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketAccept(fd, (SoftBusSockAddr *)&addr, (int32_t *)&addrLen, cfd));
306     if (ret != SOFTBUS_OK) {
307         SoftBusLog(SOFTBUS_LOG_CONN, SOFTBUS_LOG_ERROR, "accept failed, ret=%" PRId32 " cfd=%d, fd=%d", ret, *cfd, fd);
308         return ret;
309     }
310 
311     if (clientAddr != NULL) {
312         clientAddr->type = CONNECT_TCP;
313         SoftBusInetNtoP(
314             SOFTBUS_AF_INET, &addr.sinAddr, clientAddr->socketOption.addr, sizeof(clientAddr->socketOption.addr));
315         clientAddr->socketOption.port = GetTcpSockPort(*cfd);
316         clientAddr->socketOption.protocol = LNN_PROTOCOL_IP;
317     }
318     return SOFTBUS_OK;
319 }
320 
321 static SocketInterface g_ipSocketInterface = {
322     .name = "TCP",
323     .type = LNN_PROTOCOL_IP,
324     .GetSockPort = GetTcpSockPort,
325     .OpenClientSocket = OpenTcpClientSocket,
326     .OpenServerSocket = OpenTcpServerSocket,
327     .AcceptClient = AcceptTcpClient,
328 };
329 
GetTcpProtocol(void)330 const SocketInterface *GetTcpProtocol(void)
331 {
332     return &g_ipSocketInterface;
333 }
334