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