• 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 
18 #include <securec.h>
19 #include "conn_log.h"
20 #include "softbus_adapter_errcode.h"
21 #include "softbus_conn_common.h"
22 #include "softbus_error_code.h"
23 #include "softbus_socket.h"
24 
25 #define M_BYTES                     0x100000
26 #define SEND_BUF_SIZE               (4 * M_BYTES) // 4M
27 #define RECV_BUF_SIZE               (6 * M_BYTES) // 6M
28 #define USER_TIMEOUT_MS             (15 * 1000)   // 15s
29 #define SOFTBUS_TCP_USER_TIME USER_TIMEOUT_MS
30 #define SOFTBUS_CONN_TCP_USER_TIME  (35 * 1000)   // 35s
31 
32 #ifndef __LITEOS_M__
SetReusePort(int fd,int on)33 static int SetReusePort(int fd, int on)
34 {
35     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_REUSEPORT, &on, sizeof(on));
36     if (rc != 0) {
37         CONN_LOGE(CONN_COMMON, "set SO_REUSEPORT fail");
38         return -1;
39     }
40     return 0;
41 }
42 #endif
43 
SetReuseAddr(int fd,int on)44 static int SetReuseAddr(int fd, int on)
45 {
46     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_REUSEADDR, &on, sizeof(on));
47     if (rc != 0) {
48         CONN_LOGE(CONN_COMMON, "set SO_REUSEADDR fail");
49         return -1;
50     }
51     return 0;
52 }
53 
SetNoDelay(int fd,int on)54 static int SetNoDelay(int fd, int on)
55 {
56     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_NODELAY, &on, sizeof(on));
57     if (rc != 0) {
58         CONN_LOGE(CONN_COMMON, "set TCP_NODELAY fail");
59         return -1;
60     }
61     return 0;
62 }
63 
64 #ifndef TCP_QUICK_START
65 #define TCP_QUICK_START 121
66 #endif
67 
SetQuickStart(int fd,int quick)68 static int SetQuickStart(int fd, int quick)
69 {
70     errno = 0;
71     int rc = setsockopt(fd, SOFTBUS_IPPROTO_TCP, TCP_QUICK_START, &quick, sizeof(quick));
72     if (rc != 0) {
73         CONN_LOGE(CONN_COMMON, "set TCP_QUICK_START fail. rc=%{public}d, errno=%{public}d(%{public}s)",
74             rc, errno, strerror(errno));
75         return -1;
76     }
77     return 0;
78 }
79 
SetSendBufFix(int fd,int val)80 static int SetSendBufFix(int fd, int val)
81 {
82     int rc = setsockopt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_SNDBUF, &val, sizeof(val));
83     if (rc != 0) {
84         CONN_LOGE(CONN_COMMON, "set SOFTBUS_SO_SNDBUF fail. rc=%{public}d, errno=%{public}d(%{public}s)",
85             rc, errno, strerror(errno));
86         return -1;
87     }
88     return 0;
89 }
90 
SetRcvBufFix(int fd,int val)91 static int SetRcvBufFix(int fd, int val)
92 {
93     int rc = setsockopt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_RCVBUF, &val, sizeof(val));
94     if (rc != 0) {
95         CONN_LOGE(CONN_COMMON, "set SOFTBUS_SO_RCVBUF fail. rc=%{public}d, errno=%{public}d(%{public}s)",
96             rc, errno, strerror(errno));
97         return -1;
98     }
99     return 0;
100 }
101 
SetSendBuf(int fd)102 static int SetSendBuf(int fd)
103 {
104     static int sendBufSize = 0;
105     if (sendBufSize > 0) {
106         return SetSendBufFix(fd, sendBufSize);
107     }
108     // try set buffer size
109     for (int size = SEND_BUF_SIZE; size > 0; size -= M_BYTES) {
110         int ret = SetSendBufFix(fd, size);
111         if (ret == 0) {
112             sendBufSize = size;
113             return ret;
114         }
115     }
116     return -1;
117 }
118 
SetRecvBuf(int fd)119 static int SetRecvBuf(int fd)
120 {
121     static int recvBufSize = 0;
122     if (recvBufSize > 0) {
123         return SetRcvBufFix(fd, recvBufSize);
124     }
125     // try set buffer size
126     for (int size = RECV_BUF_SIZE; size > 0; size -= M_BYTES) {
127         int ret = SetRcvBufFix(fd, size);
128         if (ret == 0) {
129             recvBufSize = size;
130             return ret;
131         }
132     }
133     return -1;
134 }
135 
SetServerOption(int fd)136 void SetServerOption(int fd)
137 {
138     (void)SetReuseAddr(fd, 1);
139     (void)SetNoDelay(fd, 1);
140 #ifndef __LITEOS_M__
141     (void)SetReusePort(fd, 1);
142 #endif
143     SetSendBuf(fd);
144     SetRecvBuf(fd);
145     (void)ConnSetTcpUserTimeOut(fd, SOFTBUS_TCP_USER_TIME);
146 }
147 
SetClientOption(int fd)148 void SetClientOption(int fd)
149 {
150     SetReuseAddr(fd, 1);
151     SetNoDelay(fd, 1);
152 #ifndef __LITEOS_M__
153     SetReusePort(fd, 1);
154     SetQuickStart(fd, 1);
155 #endif
156     SetSendBuf(fd);
157     SetRecvBuf(fd);
158     (void)ConnSetTcpUserTimeOut(fd, SOFTBUS_TCP_USER_TIME);
159 }
160 
BindLocalIP(int32_t domain,int fd,const char * localIP,uint16_t port)161 int BindLocalIP(int32_t domain, int fd, const char *localIP, uint16_t port)
162 {
163     int rc = SOFTBUS_ADAPTER_OK;
164     if (domain == SOFTBUS_AF_INET6) {
165         SoftBusSockAddrIn6 addrIn6 = {0};
166         rc = Ipv6AddrToAddrIn(&addrIn6, localIP, port);
167         if (rc != SOFTBUS_OK) {
168             CONN_LOGE(CONN_COMMON, "pack ipv6 addr fail");
169             return SOFTBUS_SOCKET_ADDR_ERR;
170         }
171         return SOFTBUS_TEMP_FAILURE_RETRY(
172             SoftBusSocketBind(fd, (SoftBusSockAddr *)&addrIn6, sizeof(SoftBusSockAddrIn6)));
173     }
174     SoftBusSockAddrIn addrIn = {0};
175     rc = Ipv4AddrToAddrIn(&addrIn, localIP, port);
176     if (rc != SOFTBUS_OK) {
177         CONN_LOGE(CONN_COMMON, "pack ipv4 addr fail");
178         return SOFTBUS_SOCKET_ADDR_ERR;
179     }
180     return SOFTBUS_TEMP_FAILURE_RETRY(
181         SoftBusSocketBind(fd, (SoftBusSockAddr *)&addrIn, sizeof(SoftBusSockAddrIn)));
182 }
183 
SetIpTos(int fd,uint32_t tos)184 int32_t SetIpTos(int fd, uint32_t tos)
185 {
186     int rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_IP, SOFTBUS_IP_TOS, &tos, sizeof(tos));
187     if (rc != 0) {
188         CONN_LOGE(CONN_COMMON, "set tos fail, fd=%{public}d", fd);
189         return SOFTBUS_TCP_SOCKET_ERR;
190     }
191     return SOFTBUS_OK;
192 }
193 
SetIpv6Tos(int fd,uint32_t tos)194 static void SetIpv6Tos(int fd, uint32_t tos)
195 {
196     int32_t ret = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_IPV6, SOFTBUS_IPV6_TCLASS, &tos, sizeof(tos));
197     CONN_CHECK_AND_RETURN_LOGE(
198         ret == SOFTBUS_ADAPTER_OK, CONN_COMMON, "set tos fail, ret=%{public}d, fd=%{public}d", ret, fd);
199 }
200 
OpenTcpServerSocket(const LocalListenerInfo * option)201 static int32_t OpenTcpServerSocket(const LocalListenerInfo *option)
202 {
203     if (option == NULL) {
204         CONN_LOGE(CONN_COMMON, "invalid param!");
205         return SOFTBUS_INVALID_PARAM;
206     }
207     if (option->type != CONNECT_TCP && option->type != CONNECT_P2P && option->type != CONNECT_HML) {
208         CONN_LOGE(CONN_COMMON, "bad type! type=%{public}d", option->type);
209         return SOFTBUS_INVALID_PARAM;
210     }
211     if (option->socketOption.port < 0) {
212         CONN_LOGE(CONN_COMMON, "bad port! port=%{public}d", option->socketOption.port);
213         return SOFTBUS_INVALID_PARAM;
214     }
215 
216     int fd;
217     int32_t domain = GetDomainByAddr(option->socketOption.addr);
218     int ret = SoftBusSocketCreate(
219         domain, SOFTBUS_SOCK_STREAM | SOFTBUS_SOCK_CLOEXEC | SOFTBUS_SOCK_NONBLOCK, 0, (int32_t *)&fd);
220     if (ret != SOFTBUS_OK) {
221         CONN_LOGE(CONN_COMMON, "Create socket fail! ret=%{public}d", ret);
222         return SOFTBUS_TCP_SOCKET_ERR;
223     }
224 
225     SetServerOption(fd);
226     // tcp user timeout on the Server
227     if (option->socketOption.moduleId >= AUTH_P2P && option->socketOption.moduleId <= AUTH_ENHANCED_P2P_END) {
228         (void)ConnSetTcpUserTimeOut(fd, SOFTBUS_CONN_TCP_USER_TIME);
229     }
230     ret = BindLocalIP(domain, fd, option->socketOption.addr, (uint16_t)option->socketOption.port);
231     if (ret != SOFTBUS_OK) {
232         CONN_LOGE(CONN_COMMON, "BindLocalIP ret=%{public}d", ret);
233         ConnShutdownSocket(fd);
234         return SOFTBUS_SOCKET_BIND_ERR;
235     }
236 
237     BindToInterface(option->socketOption.addr, domain, fd, (char *)(option->socketOption.ifName), IF_NAME_SIZE);
238     CONN_LOGI(CONN_COMMON, "server listen tcp socket, fd=%{public}d", fd);
239     return fd;
240 }
241 
BindTcpClientAddr(int32_t domain,int fd,const char * inputAddr)242 int32_t BindTcpClientAddr(int32_t domain, int fd, const char *inputAddr)
243 {
244     if (inputAddr == NULL) {
245         return SOFTBUS_OK;
246     }
247 
248     const char *bindAddr = NULL;
249     if (strcmp(inputAddr, BIND_ADDR_ALL) == 0) {
250         if (domain == SOFTBUS_AF_INET6) {
251             bindAddr = "::";
252         } else {
253             bindAddr = "0.0.0.0";
254         }
255     } else {
256         CONN_LOGD(CONN_COMMON, "using specified bind addr");
257         bindAddr = inputAddr;
258     }
259     return BindLocalIP(domain, fd, bindAddr, 0);
260 }
261 
SocketConnect(int32_t fd,int32_t domain,const ConnectOption * option)262 int32_t SocketConnect(int32_t fd, int32_t domain, const ConnectOption *option)
263 {
264     int rc = SOFTBUS_ADAPTER_OK;
265     if (domain == SOFTBUS_AF_INET6) {
266         SoftBusSockAddrIn6 addrIn6 = {0};
267         rc = Ipv6AddrToAddrIn(&addrIn6, option->socketOption.addr, (uint16_t)option->socketOption.port);
268         if (rc != SOFTBUS_OK) {
269             CONN_LOGW(CONN_COMMON, "pack ipv6 addr fail");
270             return rc;
271         }
272         return SOFTBUS_TEMP_FAILURE_RETRY(
273             SoftBusSocketConnect(fd, (SoftBusSockAddr *)&addrIn6, sizeof(SoftBusSockAddrIn6)));
274     }
275     SoftBusSockAddrIn addrIn = {0};
276     rc = Ipv4AddrToAddrIn(&addrIn, option->socketOption.addr, (uint16_t)option->socketOption.port);
277     if (rc != SOFTBUS_OK) {
278         CONN_LOGE(CONN_COMMON, "pack ipv4 addr fail");
279         return rc;
280     }
281     return SOFTBUS_TEMP_FAILURE_RETRY(
282         SoftBusSocketConnect(fd, (SoftBusSockAddr *)&addrIn, sizeof(SoftBusSockAddrIn)));
283 }
284 
OpenTcpClientSocket(const ConnectOption * option,const char * myIp,bool isNonBlock)285 static int32_t OpenTcpClientSocket(const ConnectOption *option, const char *myIp, bool isNonBlock)
286 {
287     CONN_CHECK_AND_RETURN_RET_LOGW(option != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, null option");
288     CONN_CHECK_AND_RETURN_RET_LOGW(option->type == CONNECT_TCP || option->type == CONNECT_P2P ||
289         option->type == CONNECT_P2P_REUSE || option->type == CONNECT_HML, SOFTBUS_INVALID_PARAM, CONN_COMMON,
290         "invalid param, unsupport type=%{public}d", option->type);
291     CONN_CHECK_AND_RETURN_RET_LOGW(option->socketOption.port > 0, SOFTBUS_INVALID_PARAM, CONN_COMMON,
292         "invalid param, invalid port=%{public}d", option->socketOption.port);
293     CONN_CHECK_AND_RETURN_RET_LOGW(option->socketOption.addr[0] != '\0', SOFTBUS_INVALID_PARAM, CONN_COMMON,
294         "invalid param, invalid addr");
295 
296     char animizedIp[IP_LEN] = { 0 };
297     ConvertAnonymizeIpAddress(animizedIp, IP_LEN, option->socketOption.addr, IP_LEN);
298 
299     int32_t fd = -1;
300     int32_t domain = GetDomainByAddr(option->socketOption.addr);
301     int32_t ret = SoftBusSocketCreate(domain, SOFTBUS_SOCK_STREAM, 0, &fd);
302     CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_COMMON,
303         "create socket fail, serverIp=%{public}s, serverPort=%{public}d, error=%{public}d", animizedIp,
304         option->socketOption.port, ret);
305 
306     if (isNonBlock && ConnToggleNonBlockMode(fd, true) != SOFTBUS_OK) {
307         CONN_LOGE(CONN_COMMON, "set nonblock fail, serverIp=%{public}s, serverPort=%{public}d, fd=%{public}d",
308             animizedIp, option->socketOption.port, fd);
309         SoftBusSocketClose(fd);
310         return SOFTBUS_TCPCONNECTION_SOCKET_ERR;
311     }
312     SetClientOption(fd);
313     // tcp user timeout on the Client
314     if (option->socketOption.moduleId >= AUTH_P2P && option->socketOption.moduleId <= AUTH_ENHANCED_P2P_END) {
315         (void)ConnSetTcpUserTimeOut(fd, SOFTBUS_CONN_TCP_USER_TIME);
316         if (domain == SOFTBUS_AF_INET6) {
317             SetIpv6Tos(fd, IPV6_MESSAGE_TOS);
318         }
319     }
320     ret = BindTcpClientAddr(domain, fd, myIp);
321     if (ret != SOFTBUS_OK) {
322         CONN_LOGE(CONN_COMMON, "bind client address fail, serverIp=%{public}s, serverPort=%{public}d, "
323             "error=%{public}d", animizedIp, option->socketOption.port, ret);
324         ConnShutdownSocket(fd);
325         return ret;
326     }
327 
328     BindToInterface(myIp, domain, fd, (char *)(option->socketOption.ifName), IF_NAME_SIZE);
329     ret = SocketConnect(fd, domain, option);
330     if ((ret != SOFTBUS_ADAPTER_OK) && (ret != SOFTBUS_ADAPTER_SOCKET_EINPROGRESS) &&
331         (ret != SOFTBUS_ADAPTER_SOCKET_EAGAIN)) {
332         CONN_LOGE(CONN_COMMON, "client connect fail, serverIp=%{public}s, serverPort=%{public}d, fd=%{public}d, "
333             "ret=%{public}d, errno=%{public}d(%{public}s)", animizedIp, option->socketOption.port, fd, ret,
334             errno, strerror(errno));
335         ConnShutdownSocket(fd);
336         return ret;
337     }
338     CONN_LOGI(CONN_COMMON, "client open tcp socket, serverIp=%{public}s, serverPort=%{public}d, fd=%{public}d",
339         animizedIp, option->socketOption.port, fd);
340     return fd;
341 }
342 
GetTcpSockPort(int32_t fd)343 int32_t GetTcpSockPort(int32_t fd)
344 {
345     SoftBusSockAddr addr;
346     int rc = SoftBusSocketGetLocalName(fd, &addr);
347     if (rc != 0) {
348         CONN_LOGE(CONN_COMMON, "fd=%{public}d, rc=%{public}d", fd, rc);
349         return rc;
350     }
351     if (addr.saFamily == SOFTBUS_AF_INET6) {
352         return SoftBusNtoHs(((SoftBusSockAddrIn6 *)&addr)->sin6Port);
353     }
354     return SoftBusNtoHs(((SoftBusSockAddrIn *)&addr)->sinPort);
355 }
356 
ConnSetTcpKeepaliveState(int32_t fd,bool needKeepalive)357 int32_t ConnSetTcpKeepaliveState(int32_t fd, bool needKeepalive)
358 {
359     CONN_CHECK_AND_RETURN_RET_LOGE(fd >= 0, SOFTBUS_NOT_FIND, CONN_COMMON, "invalid param");
360     int32_t enable = needKeepalive ? 1 : 0;
361     int32_t ret = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_KEEPALIVE, &enable, sizeof(enable));
362     if (ret != SOFTBUS_ADAPTER_OK) {
363         CONN_LOGE(CONN_COMMON, "set SO_KEEPALIVE fail, ret=%{public}d", ret);
364         return SOFTBUS_ADAPTER_ERR;
365     }
366     return SOFTBUS_ADAPTER_OK;
367 }
368 
ConnSetTcpKeepalive(int32_t fd,int32_t seconds,int32_t keepAliveIntvl,int32_t keepAliveCount)369 int32_t ConnSetTcpKeepalive(int32_t fd, int32_t seconds, int32_t keepAliveIntvl, int32_t keepAliveCount)
370 {
371     if (fd <= 0 || seconds <= 0 || keepAliveIntvl <= 0 || keepAliveCount <= 0) {
372         CONN_LOGE(CONN_COMMON, "ConnSetTcpKeepalive invalid param");
373         return SOFTBUS_INVALID_PARAM;
374     }
375 
376     int32_t rc;
377     rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_KEEPIDLE, &seconds, sizeof(seconds));
378     if (rc != SOFTBUS_ADAPTER_OK) {
379         CONN_LOGE(CONN_COMMON, "set TCP_KEEPIDLE fail");
380         return SOFTBUS_ADAPTER_ERR;
381     }
382 
383     rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_KEEPCNT, &keepAliveCount, sizeof(keepAliveCount));
384     if (rc != SOFTBUS_ADAPTER_OK) {
385         CONN_LOGE(CONN_COMMON, "set TCP_KEEPCNT fail");
386         return SOFTBUS_ADAPTER_ERR;
387     }
388 
389     rc = SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_KEEPINTVL, &keepAliveIntvl, sizeof(keepAliveIntvl));
390     if (rc != SOFTBUS_ADAPTER_OK) {
391         CONN_LOGE(CONN_COMMON, "set TCP_KEEPINTVL fail");
392         return SOFTBUS_ADAPTER_ERR;
393     }
394 
395     return ConnSetTcpKeepaliveState(fd, true);
396 }
397 
398 #ifdef TCP_USER_TIMEOUT
ConnSetTcpUserTimeOut(int32_t fd,uint32_t millSec)399 int32_t ConnSetTcpUserTimeOut(int32_t fd, uint32_t millSec)
400 {
401     if (fd < 0) {
402         CONN_LOGE(CONN_COMMON, "invalid param");
403         return SOFTBUS_ADAPTER_ERR;
404     }
405     if (SoftBusSocketSetOpt(fd, SOFTBUS_IPPROTO_TCP, SOFTBUS_TCP_USER_TIMEOUT, &millSec, sizeof(millSec)) !=
406         SOFTBUS_ADAPTER_OK) {
407         CONN_LOGE(CONN_COMMON, "set SOFTBUS_TCP_USER_TIMEOUT fail");
408         return SOFTBUS_ADAPTER_ERR;
409     }
410     return SOFTBUS_OK;
411 }
412 #else
ConnSetTcpUserTimeOut(int32_t fd,uint32_t millSec)413 int32_t ConnSetTcpUserTimeOut(int32_t fd, uint32_t millSec)
414 {
415     (void)fd;
416     (void)millSec;
417     return 0;
418 }
419 
420 #endif
421 
AcceptTcpClient(int32_t fd,ConnectOption * clientAddr,int32_t * cfd)422 static int32_t AcceptTcpClient(int32_t fd, ConnectOption *clientAddr, int32_t *cfd)
423 {
424     CONN_CHECK_AND_RETURN_RET_LOGW(clientAddr != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON,
425         "invalid param, clientAddr is null");
426     SoftBusSockAddr addr;
427     (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr));
428     int32_t ret = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketAccept(fd, &addr, cfd));
429     if (ret != SOFTBUS_OK) {
430         CONN_LOGE(CONN_COMMON, "accept fail, ret=%{public}" PRId32 ", cfd=%{public}d, fd=%{public}d", ret, *cfd, fd);
431         return ret;
432     }
433 
434     clientAddr->type = CONNECT_TCP;
435     clientAddr->socketOption.port = GetTcpSockPort(*cfd);
436     clientAddr->socketOption.protocol = LNN_PROTOCOL_IP;
437     if (addr.saFamily == SOFTBUS_AF_INET6) {
438         ret = Ipv6AddrInToAddr((SoftBusSockAddrIn6 *)&addr,
439             clientAddr->socketOption.addr, sizeof(clientAddr->socketOption.addr));
440         if (ret < 0) {
441             CONN_LOGE(CONN_COMMON, "get ipv6 addr fail");
442             return ret;
443         }
444         return SOFTBUS_OK;
445     }
446     if (SoftBusInetNtoP(SOFTBUS_AF_INET, &((SoftBusSockAddrIn *)&addr)->sinAddr,
447         clientAddr->socketOption.addr, sizeof(clientAddr->socketOption.addr)) == NULL) {
448         CONN_LOGE(CONN_COMMON, "get addr fail");
449         return SOFTBUS_TCPCONNECTION_SOCKET_ERR;
450     }
451     return SOFTBUS_OK;
452 }
453 
GetTcpProtocol(void)454 const SocketInterface *GetTcpProtocol(void)
455 {
456     static SocketInterface tcpSocketIntf = {
457         .name = "TCP",
458         .type = LNN_PROTOCOL_IP,
459         .GetSockPort = GetTcpSockPort,
460         .OpenClientSocket = OpenTcpClientSocket,
461         .OpenServerSocket = OpenTcpServerSocket,
462         .AcceptClient = AcceptTcpClient,
463     };
464     return &tcpSocketIntf;
465 }