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 }