blob: 2efdaba6c3222dc39b3f48e9bde01116ceaf9be6 [file] [log] [blame]
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -05001/*
2 *
3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2013-2018 Nest Labs, Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/**
20 * This file implements Inet::TCPEndPoint using sockets.
21 */
22
23#include <inet/TCPEndPointImplSockets.h>
24
25#include <inet/InetFaultInjection.h>
26#include <inet/arpa-inet-compatibility.h>
27
28#include <lib/support/CodeUtils.h>
29#include <lib/support/SafeInt.h>
30#include <lib/support/logging/CHIPLogging.h>
31#include <system/SystemFaultInjection.h>
32
33#include <stdio.h>
34#include <string.h>
35#include <utility>
36
37#include <errno.h>
38#include <fcntl.h>
39#include <net/if.h>
40#include <netinet/tcp.h>
41#include <sys/ioctl.h>
42#include <sys/select.h>
43#include <sys/socket.h>
44#include <unistd.h>
45
46// SOCK_CLOEXEC not defined on all platforms, e.g. iOS/macOS:
47#ifndef SOCK_CLOEXEC
48#define SOCK_CLOEXEC 0
49#endif
50
51#if defined(SOL_TCP)
52// socket option level for Linux and BSD systems.
53#define TCP_SOCKOPT_LEVEL SOL_TCP
54#else
55// socket option level for macOS & iOS systems.
56#define TCP_SOCKOPT_LEVEL IPPROTO_TCP
57#endif
58
59#if defined(TCP_KEEPIDLE)
60// socket option for Linux and BSD systems.
61#define TCP_IDLE_INTERVAL_OPT_NAME TCP_KEEPIDLE
62#else
63// socket option for macOS & iOS systems.
64#define TCP_IDLE_INTERVAL_OPT_NAME TCP_KEEPALIVE
65#endif
66
67namespace chip {
68namespace Inet {
69
70CHIP_ERROR TCPEndPointImplSockets::BindImpl(IPAddressType addrType, const IPAddress & addr, uint16_t port, bool reuseAddr)
71{
72 CHIP_ERROR res = GetSocket(addrType);
73
74 if (res == CHIP_NO_ERROR && reuseAddr)
75 {
76 int n = 1;
77 setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
78
79#ifdef SO_REUSEPORT
80 // Enable SO_REUSEPORT. This permits coexistence between an
81 // untargetted CHIP client and other services that listen on
82 // a CHIP port on a specific address (such as a CHIP client
Martin Turond24eff12021-12-17 06:21:23 -080083 // with TARGETED_LISTEN or TCP proxying services). Note that
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -050084 // one of the costs of this implementation is the
85 // non-deterministic connection dispatch when multple clients
Martin Turond24eff12021-12-17 06:21:23 -080086 // listen on the address with the same degreee of selectivity,
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -050087 // e.g. two untargetted-listen CHIP clients, or two
Martin Turond24eff12021-12-17 06:21:23 -080088 // targeted-listen CHIP clients with the same node id.
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -050089
90 if (setsockopt(mSocket, SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n)) != 0)
91 {
92 ChipLogError(Inet, "SO_REUSEPORT: %d", errno);
93 }
94#endif // defined(SO_REUSEPORT)
95 }
96
97 if (res == CHIP_NO_ERROR)
98 {
99 if (addrType == IPAddressType::kIPv6)
100 {
101 struct sockaddr_in6 sa;
102 memset(&sa, 0, sizeof(sa));
103 sa.sin6_family = AF_INET6;
104 sa.sin6_port = htons(port);
105 sa.sin6_flowinfo = 0;
106 sa.sin6_addr = addr.ToIPv6();
107 sa.sin6_scope_id = 0;
108
109 if (bind(mSocket, reinterpret_cast<const sockaddr *>(&sa), static_cast<unsigned>(sizeof(sa))) != 0)
110 {
111 res = CHIP_ERROR_POSIX(errno);
112 }
113 }
114#if INET_CONFIG_ENABLE_IPV4
115 else if (addrType == IPAddressType::kIPv4)
116 {
117 struct sockaddr_in sa;
118 memset(&sa, 0, sizeof(sa));
119 sa.sin_family = AF_INET;
120 sa.sin_port = htons(port);
121 sa.sin_addr = addr.ToIPv4();
122
123 if (bind(mSocket, reinterpret_cast<const sockaddr *>(&sa), static_cast<unsigned>(sizeof(sa))) != 0)
124 {
125 res = CHIP_ERROR_POSIX(errno);
126 }
127 }
128#endif // INET_CONFIG_ENABLE_IPV4
129 else
130 {
131 res = INET_ERROR_WRONG_ADDRESS_TYPE;
132 }
133 }
134
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500135 return res;
136}
137
138CHIP_ERROR TCPEndPointImplSockets::ListenImpl(uint16_t backlog)
139{
140 if (listen(mSocket, backlog) != 0)
141 {
142 return CHIP_ERROR_POSIX(errno);
143 }
144
145 // Enable non-blocking mode for the socket.
146 int flags = fcntl(mSocket, F_GETFL, 0);
147 fcntl(mSocket, F_SETFL, flags | O_NONBLOCK);
148
149 // Wait for ability to read on this endpoint.
150 CHIP_ERROR res = static_cast<System::LayerSockets &>(GetSystemLayer())
151 .SetCallback(mWatch, HandlePendingIO, reinterpret_cast<intptr_t>(this));
152 if (res == CHIP_NO_ERROR)
153 {
154 res = static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingRead(mWatch);
155 }
156
157 return res;
158}
159
160CHIP_ERROR TCPEndPointImplSockets::ConnectImpl(const IPAddress & addr, uint16_t port, InterfaceId intfId)
161{
162 IPAddressType addrType = addr.Type();
163
164 ReturnErrorOnFailure(GetSocket(addrType));
165
166 if (!intfId.IsPresent())
167 {
168 // The behavior when connecting to an IPv6 link-local address without specifying an outbound
169 // interface is ambiguous. So prevent it in all cases.
170 if (addr.IsIPv6LinkLocal())
171 {
172 return INET_ERROR_WRONG_ADDRESS_TYPE;
173 }
174 }
175 else
176 {
177 // Try binding to the interface
178
179 // If destination is link-local then there is no need to bind to
180 // interface or address on the interface.
181
182 if (!addr.IsIPv6LinkLocal())
183 {
184#ifdef SO_BINDTODEVICE
185 struct ::ifreq ifr;
186 memset(&ifr, 0, sizeof(ifr));
187
188 ReturnErrorOnFailure(intfId.GetInterfaceName(ifr.ifr_name, sizeof(ifr.ifr_name)));
189
190 // Attempt to bind to the interface using SO_BINDTODEVICE which requires privileged access.
191 // If the permission is denied(EACCES) because CHIP is running in a context
192 // that does not have privileged access, choose a source address on the
193 // interface to bind the connetion to.
194 int r = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
195 if (r < 0 && errno != EACCES)
196 {
197 return CHIP_ERROR_POSIX(errno);
198 }
199
200 if (r < 0)
201#endif // SO_BINDTODEVICE
202 {
203 // Attempting to initiate a connection via a specific interface is not allowed.
204 // The only way to do this is to bind the local to an address on the desired
205 // interface.
206 ReturnErrorOnFailure(BindSrcAddrFromIntf(addrType, intfId));
207 }
208 }
209 }
210
211 // Disable generation of SIGPIPE.
212#ifdef SO_NOSIGPIPE
213 int n = 1;
214 setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &n, sizeof(n));
215#endif // defined(SO_NOSIGPIPE)
216
217 // Enable non-blocking mode for the socket.
218 int flags = fcntl(mSocket, F_GETFL, 0);
219 fcntl(mSocket, F_SETFL, flags | O_NONBLOCK);
220
221 socklen_t sockaddrsize = 0;
222 const sockaddr * sockaddrptr = nullptr;
223
224 SockAddr sa;
225 memset(&sa, 0, sizeof(sa));
226
227 if (addrType == IPAddressType::kIPv6)
228 {
229 sa.in6.sin6_family = AF_INET6;
230 sa.in6.sin6_port = htons(port);
231 sa.in6.sin6_flowinfo = 0;
232 sa.in6.sin6_addr = addr.ToIPv6();
233 sa.in6.sin6_scope_id = intfId.GetPlatformInterface();
234 sockaddrsize = sizeof(sockaddr_in6);
235 sockaddrptr = reinterpret_cast<const sockaddr *>(&sa.in6);
236 }
237#if INET_CONFIG_ENABLE_IPV4
238 else if (addrType == IPAddressType::kIPv4)
239 {
240 sa.in.sin_family = AF_INET;
241 sa.in.sin_port = htons(port);
242 sa.in.sin_addr = addr.ToIPv4();
243 sockaddrsize = sizeof(sockaddr_in);
244 sockaddrptr = reinterpret_cast<const sockaddr *>(&sa.in);
245 }
246#endif // INET_CONFIG_ENABLE_IPV4
247 else
248 {
249 return INET_ERROR_WRONG_ADDRESS_TYPE;
250 }
251
252 int conRes = connect(mSocket, sockaddrptr, sockaddrsize);
253
254 if (conRes == -1 && errno != EINPROGRESS)
255 {
256 CHIP_ERROR res = CHIP_ERROR_POSIX(errno);
257 DoClose(res, true);
258 return res;
259 }
260
261 ReturnErrorOnFailure(static_cast<System::LayerSockets &>(GetSystemLayer())
262 .SetCallback(mWatch, HandlePendingIO, reinterpret_cast<intptr_t>(this)));
263
264 // Once Connecting or Connected, bump the reference count. The corresponding Release() will happen in DoClose().
265 Retain();
266
267 if (conRes == 0)
268 {
269 mState = State::kConnected;
270 // Wait for ability to read on this endpoint.
271 ReturnErrorOnFailure(static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingRead(mWatch));
272 if (OnConnectComplete != nullptr)
273 {
274 OnConnectComplete(this, CHIP_NO_ERROR);
275 }
276 }
277 else
278 {
279 mState = State::kConnecting;
280 // Wait for ability to write on this endpoint.
281 ReturnErrorOnFailure(static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingWrite(mWatch));
282 }
283
284 return CHIP_NO_ERROR;
285}
286
287CHIP_ERROR TCPEndPointImplSockets::GetPeerInfo(IPAddress * retAddr, uint16_t * retPort) const
288{
289 return GetSocketInfo(getpeername, retAddr, retPort);
290}
291
292CHIP_ERROR TCPEndPointImplSockets::GetLocalInfo(IPAddress * retAddr, uint16_t * retPort) const
293{
294 return GetSocketInfo(getsockname, retAddr, retPort);
295}
296
297CHIP_ERROR TCPEndPointImplSockets::GetSocketInfo(int getname(int, sockaddr *, socklen_t *), IPAddress * retAddr,
298 uint16_t * retPort) const
299{
300 VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
301
302 SockAddr sa;
303 memset(&sa, 0, sizeof(sa));
304 socklen_t saLen = sizeof(sa);
305
306 if (getname(mSocket, &sa.any, &saLen) != 0)
307 {
308 return CHIP_ERROR_POSIX(errno);
309 }
310
311 if (sa.any.sa_family == AF_INET6)
312 {
313 *retAddr = IPAddress(sa.in6.sin6_addr);
314 *retPort = ntohs(sa.in6.sin6_port);
315 return CHIP_NO_ERROR;
316 }
317
318#if INET_CONFIG_ENABLE_IPV4
319 if (sa.any.sa_family == AF_INET)
320 {
321 *retAddr = IPAddress(sa.in.sin_addr);
322 *retPort = ntohs(sa.in.sin_port);
323 return CHIP_NO_ERROR;
324 }
325#endif // INET_CONFIG_ENABLE_IPV4
326
327 return CHIP_ERROR_INCORRECT_STATE;
328}
329
330CHIP_ERROR TCPEndPointImplSockets::GetInterfaceId(InterfaceId * retInterface)
331{
332 VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
333
334 SockAddr sa;
335 memset(&sa, 0, sizeof(sa));
336 socklen_t saLen = sizeof(sa);
337
338 if (getpeername(mSocket, &sa.any, &saLen) != 0)
339 {
340 return CHIP_ERROR_POSIX(errno);
341 }
342
343 if (sa.any.sa_family == AF_INET6)
344 {
345 if (IPAddress(sa.in6.sin6_addr).IsIPv6LinkLocal())
346 {
347 *retInterface = InterfaceId(sa.in6.sin6_scope_id);
348 }
349 else
350 {
351 // TODO: Is there still a meaningful interface id in this case?
352 *retInterface = InterfaceId::Null();
353 }
354 return CHIP_NO_ERROR;
355 }
356
357#if INET_CONFIG_ENABLE_IPV4
358 if (sa.any.sa_family == AF_INET)
359 {
360 // No interface id available for IPv4 sockets.
361 *retInterface = InterfaceId::Null();
362 return CHIP_NO_ERROR;
363 }
364#endif // INET_CONFIG_ENABLE_IPV4
365
366 *retInterface = InterfaceId::Null();
367 return INET_ERROR_WRONG_ADDRESS_TYPE;
368}
369
370CHIP_ERROR TCPEndPointImplSockets::SendQueuedImpl(bool queueWasEmpty)
371{
372 if (queueWasEmpty)
373 {
374 // Wait for ability to write on this endpoint.
375 return static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingWrite(mWatch);
376 }
377 return CHIP_NO_ERROR;
378}
379
380CHIP_ERROR TCPEndPointImplSockets::EnableNoDelay()
381{
382 VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
383
384#ifdef TCP_NODELAY
385 // Disable TCP Nagle buffering by setting TCP_NODELAY socket option to true
386 int val = 1;
387 if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_NODELAY, &val, sizeof(val)) != 0)
388 {
389 return CHIP_ERROR_POSIX(errno);
390 }
391#endif // defined(TCP_NODELAY)
392
393 return CHIP_NO_ERROR;
394}
395
396CHIP_ERROR TCPEndPointImplSockets::EnableKeepAlive(uint16_t interval, uint16_t timeoutCount)
397{
398 VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
399
400 // Set the idle interval
401 int val = interval;
402 if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_IDLE_INTERVAL_OPT_NAME, &val, sizeof(val)) != 0)
403 {
404 return CHIP_ERROR_POSIX(errno);
405 }
406
407 // Set the probe retransmission interval.
408 val = interval;
409 if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_KEEPINTVL, &val, sizeof(val)) != 0)
410 {
411 return CHIP_ERROR_POSIX(errno);
412 }
413
414 // Set the probe timeout count
415 val = timeoutCount;
416 if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_KEEPCNT, &val, sizeof(val)) != 0)
417 {
418 return CHIP_ERROR_POSIX(errno);
419 }
420
421 // Enable keepalives for the connection.
422 val = 1; // enable
423 if (setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0)
424 {
425 return CHIP_ERROR_POSIX(errno);
426 }
427
428 return CHIP_NO_ERROR;
429}
430
431CHIP_ERROR TCPEndPointImplSockets::DisableKeepAlive()
432{
433 VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
434
435 // Disable keepalives on the connection.
436 int val = 0; // disable
437 if (setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0)
438 {
439 return CHIP_ERROR_POSIX(errno);
440 }
441
442 return CHIP_NO_ERROR;
443}
444
445CHIP_ERROR TCPEndPointImplSockets::AckReceive(uint16_t len)
446{
447 VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
448
449 // nothing to do for sockets case
450 return CHIP_NO_ERROR;
451}
452
453CHIP_ERROR TCPEndPointImplSockets::SetUserTimeoutImpl(uint32_t userTimeoutMillis)
454{
455#if defined(TCP_USER_TIMEOUT)
456 // Set the user timeout
457 uint32_t val = userTimeoutMillis;
458 if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_USER_TIMEOUT, &val, sizeof(val)) != 0)
459 {
460 return CHIP_ERROR_POSIX(errno);
461 }
462 return CHIP_NO_ERROR;
463#else // TCP_USER_TIMEOUT
464 return CHIP_ERROR_NOT_IMPLEMENTED;
465#endif // defined(TCP_USER_TIMEOUT)
466}
467
468CHIP_ERROR TCPEndPointImplSockets::DriveSendingImpl()
469{
470 CHIP_ERROR err = CHIP_NO_ERROR;
471
472#ifdef MSG_NOSIGNAL
473 const int sendFlags = MSG_NOSIGNAL;
474#else
475 const int sendFlags = 0;
476#endif
477
478 // Pretend send() fails in the while loop below
479 INET_FAULT_INJECT(FaultInjection::kFault_Send, {
480 err = CHIP_ERROR_POSIX(EIO);
481 DoClose(err, false);
482 return err;
483 });
484
485 while (!mSendQueue.IsNull())
486 {
487 uint16_t bufLen = mSendQueue->DataLength();
488
489 ssize_t lenSentRaw = send(mSocket, mSendQueue->Start(), bufLen, sendFlags);
490
491 if (lenSentRaw == -1)
492 {
493 if (errno != EAGAIN && errno != EWOULDBLOCK)
494 {
495 err = (errno == EPIPE) ? INET_ERROR_PEER_DISCONNECTED : CHIP_ERROR_POSIX(errno);
496 }
497 break;
498 }
499
500 if (lenSentRaw < 0 || lenSentRaw > bufLen)
501 {
502 err = CHIP_ERROR_INCORRECT_STATE;
503 break;
504 }
505
506 // Cast is safe because bufLen is uint16_t.
507 uint16_t lenSent = static_cast<uint16_t>(lenSentRaw);
508
509 // Mark the connection as being active.
510 MarkActive();
511
512 if (lenSent < bufLen)
513 {
514 mSendQueue->ConsumeHead(lenSent);
515 }
516 else
517 {
518 mSendQueue.FreeHead();
519 if (mSendQueue.IsNull())
520 {
521 // Do not wait for ability to write on this endpoint.
522 err = static_cast<System::LayerSockets &>(GetSystemLayer()).ClearCallbackOnPendingWrite(mWatch);
523 if (err != CHIP_NO_ERROR)
524 {
525 break;
526 }
527 }
528 }
529
530 if (OnDataSent != nullptr)
531 {
532 OnDataSent(this, lenSent);
533 }
534
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500535#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
536 mBytesWrittenSinceLastProbe += lenSent;
537
538 bool isProgressing = false;
539
540 err = CheckConnectionProgress(isProgressing);
541 if (err != CHIP_NO_ERROR)
542 {
543 break;
544 }
545
546 if (!mUserTimeoutTimerRunning)
547 {
548 // Timer was not running before this write. So, start
549 // the timer.
550
551 StartTCPUserTimeoutTimer();
552 }
553 else if (isProgressing)
554 {
555 // Progress is being made. So, shift the timer
556 // forward if it was started.
557
558 RestartTCPUserTimeoutTimer();
559 }
560#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
561
562 if (lenSent < bufLen)
563 {
564 break;
565 }
566 }
567
568 if (err == CHIP_NO_ERROR)
569 {
570 // If we're in the SendShutdown state and the send queue is now empty, shutdown writing on the socket.
571 if (mState == State::kSendShutdown && mSendQueue.IsNull())
572 {
573 if (shutdown(mSocket, SHUT_WR) != 0)
574 {
575 err = CHIP_ERROR_POSIX(errno);
576 }
577 }
578 }
579
580 return err;
581}
582
583void TCPEndPointImplSockets::HandleConnectCompleteImpl()
584{
585 // Wait for ability to read or write on this endpoint.
586 CHIP_ERROR err = static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingRead(mWatch);
587 if (err == CHIP_NO_ERROR)
588 {
589 err = static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingWrite(mWatch);
590 }
591 if (err != CHIP_NO_ERROR)
592 {
593 DoClose(err, false);
594 return;
595 }
596}
597
598void TCPEndPointImplSockets::DoCloseImpl(CHIP_ERROR err, State oldState)
599{
600 struct linger lingerStruct;
601
602 // If the socket hasn't been closed already...
603 if (mSocket != kInvalidSocketFd)
604 {
605 // If entering the Closed state
606 // OR if entering the Closing state, and there's no unsent data in the send queue
607 // THEN close the socket.
608 if (mState == State::kClosed || (mState == State::kClosing && mSendQueue.IsNull()))
609 {
610 // If aborting the connection, ensure we send a TCP RST.
611 if (IsConnected(oldState) && err != CHIP_NO_ERROR)
612 {
613 lingerStruct.l_onoff = 1;
614 lingerStruct.l_linger = 0;
615
616 if (setsockopt(mSocket, SOL_SOCKET, SO_LINGER, &lingerStruct, sizeof(lingerStruct)) != 0)
617 {
618 ChipLogError(Inet, "SO_LINGER: %d", errno);
619 }
620 }
621
622 static_cast<System::LayerSockets &>(GetSystemLayer()).StopWatchingSocket(&mWatch);
623 close(mSocket);
624 mSocket = kInvalidSocketFd;
625 }
626 }
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500627}
628
629#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
630void TCPEndPointImplSockets::TCPUserTimeoutHandler()
631{
632 // Set the timer running flag to false
633 mUserTimeoutTimerRunning = false;
634
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500635 bool isProgressing = false;
Kevin Schoedel92b9ef82021-12-21 20:45:39 -0500636 CHIP_ERROR err = CheckConnectionProgress(isProgressing);
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500637
Kevin Schoedel92b9ef82021-12-21 20:45:39 -0500638 if (err == CHIP_NO_ERROR && mLastTCPKernelSendQueueLen != 0)
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500639 {
Kevin Schoedel92b9ef82021-12-21 20:45:39 -0500640 // There is data in the TCP Send Queue
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500641 if (isProgressing)
642 {
643 // Data is flowing, so restart the UserTimeout timer
644 // to shift it forward while also resetting the max
645 // poll count.
646
647 StartTCPUserTimeoutTimer();
648 }
649 else
650 {
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500651 // Close the connection as the TCP UserTimeout has expired
Kevin Schoedel92b9ef82021-12-21 20:45:39 -0500652 err = INET_ERROR_TCP_USER_TIMEOUT;
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500653 }
654 }
655
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500656 if (err != CHIP_NO_ERROR)
657 {
658 // Close the connection as the TCP UserTimeout has expired
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500659 DoClose(err, false);
660 }
661}
662#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
663
664CHIP_ERROR TCPEndPointImplSockets::BindSrcAddrFromIntf(IPAddressType addrType, InterfaceId intfId)
665{
666 // If we are trying to make a TCP connection over a 'specified target interface',
667 // then we bind the TCPEndPoint to an IP address on that target interface
668 // and use that address as the source address for that connection. This is
669 // done in the event that directly binding the connection to the target
670 // interface is not allowed due to insufficient privileges.
671 VerifyOrReturnError(mState != State::kBound, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
672
673 bool ipAddrFound = false;
674 for (InterfaceAddressIterator addrIter; addrIter.HasCurrent(); addrIter.Next())
675 {
Kevin Schoedelf86f21f2021-12-16 07:17:46 -0500676 IPAddress curAddr;
677 if ((addrIter.GetInterfaceId() == intfId) && (addrIter.GetAddress(curAddr) == CHIP_NO_ERROR))
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500678 {
679 // Search for an IPv4 address on the TargetInterface
680
681#if INET_CONFIG_ENABLE_IPV4
682 if (addrType == IPAddressType::kIPv4)
683 {
684 if (curAddr.IsIPv4())
685 {
686 // Bind to the IPv4 address of the TargetInterface
687 ipAddrFound = true;
688 ReturnErrorOnFailure(Bind(IPAddressType::kIPv4, curAddr, 0, true));
689
690 break;
691 }
692 }
693#endif // INET_CONFIG_ENABLE_IPV4
694 if (addrType == IPAddressType::kIPv6)
695 {
696 // Select an IPv6 address on the interface that is not
697 // a link local or a multicast address.
698 // TODO: Define a proper IPv6GlobalUnicast address checker.
699 if (!curAddr.IsIPv4() && !curAddr.IsIPv6LinkLocal() && !curAddr.IsMulticast())
700 {
701 // Bind to the IPv6 address of the TargetInterface
702 ipAddrFound = true;
703 ReturnErrorOnFailure(Bind(IPAddressType::kIPv6, curAddr, 0, true));
704
705 break;
706 }
707 }
708 }
709 }
710
711 VerifyOrReturnError(ipAddrFound, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
712
713 return CHIP_NO_ERROR;
714}
715
716CHIP_ERROR TCPEndPointImplSockets::GetSocket(IPAddressType addrType)
717{
718 if (mSocket == kInvalidSocketFd)
719 {
720 int family;
721 if (addrType == IPAddressType::kIPv6)
722 {
723 family = PF_INET6;
724#if INET_CONFIG_ENABLE_IPV4
725 }
726 else if (addrType == IPAddressType::kIPv4)
727 {
728 family = PF_INET;
729#endif // INET_CONFIG_ENABLE_IPV4
730 }
731 else
732 {
733 return INET_ERROR_WRONG_ADDRESS_TYPE;
734 }
735 mSocket = ::socket(family, SOCK_STREAM | SOCK_CLOEXEC, 0);
736 if (mSocket == -1)
737 {
738 return CHIP_ERROR_POSIX(errno);
739 }
740 ReturnErrorOnFailure(static_cast<System::LayerSockets &>(GetSystemLayer()).StartWatchingSocket(mSocket, &mWatch));
741 mAddrType = addrType;
742
743 // If creating an IPv6 socket, tell the kernel that it will be IPv6 only. This makes it
744 // posible to bind two sockets to the same port, one for IPv4 and one for IPv6.
745#ifdef IPV6_V6ONLY
746 if (family == PF_INET6)
747 {
748 int one = 1;
749 setsockopt(mSocket, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
750 }
751#endif // defined(IPV6_V6ONLY)
752
753 // On systems that support it, disable the delivery of SIGPIPE signals when writing to a closed
754 // socket.
755#ifdef SO_NOSIGPIPE
756 {
757 int one = 1;
758 int res = setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one));
759 if (res != 0)
760 {
761 ChipLogError(Inet, "SO_NOSIGPIPE: %d", errno);
762 }
763 }
764#endif // defined(SO_NOSIGPIPE)
765 }
766 else if (mAddrType != addrType)
767 {
768 return CHIP_ERROR_INCORRECT_STATE;
769 }
770
771 return CHIP_NO_ERROR;
772}
773
774// static
775void TCPEndPointImplSockets::HandlePendingIO(System::SocketEvents events, intptr_t data)
776{
777 reinterpret_cast<TCPEndPointImplSockets *>(data)->HandlePendingIO(events);
778}
779
780void TCPEndPointImplSockets::HandlePendingIO(System::SocketEvents events)
781{
782 // Prevent the end point from being freed while in the middle of a callback.
783 Retain();
784
785 // If in the Listening state, and the app is ready to receive a connection, and there is a connection
786 // ready to be received on the socket, process the incoming connection.
787 if (mState == State::kListening)
788 {
789 if (OnConnectionReceived != nullptr && events.Has(System::SocketEventFlags::kRead))
790 {
791 HandleIncomingConnection();
792 }
793 }
794
795 // If in the processes of initiating a connection...
796 else if (mState == State::kConnecting)
797 {
798 // The socket being writable indicates the connection has completed (successfully or otherwise).
799 if (events.Has(System::SocketEventFlags::kWrite))
800 {
801#if !__MBED__
802 // Get the connection result from the socket.
803 int osConRes;
804 socklen_t optLen = sizeof(osConRes);
805 if (getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &osConRes, &optLen) != 0)
806 {
807 osConRes = errno;
808 }
809#else
810 // On Mbed OS, connect blocks and never returns EINPROGRESS
811 // The socket option SO_ERROR is not available.
812 int osConRes = 0;
813#endif
814 CHIP_ERROR conRes = CHIP_ERROR_POSIX(osConRes);
815
816 // Process the connection result.
817 HandleConnectComplete(conRes);
818 }
819 }
820
821 else
822 {
823 // If in a state where sending is allowed, and there is data to be sent, and the socket is ready for
824 // writing, drive outbound data into the connection.
825 if (IsConnected() && !mSendQueue.IsNull() && events.Has(System::SocketEventFlags::kWrite))
826 {
827 DriveSending();
828 }
829
830 // If in a state were receiving is allowed, and the app is ready to receive data, and data is ready
831 // on the socket, receive inbound data from the connection.
832 if ((mState == State::kConnected || mState == State::kSendShutdown) && mReceiveEnabled && OnDataReceived != nullptr &&
833 events.Has(System::SocketEventFlags::kRead))
834 {
835 ReceiveData();
836 }
837 }
838
839 Release();
840}
841
842void TCPEndPointImplSockets::ReceiveData()
843{
844 System::PacketBufferHandle rcvBuf;
845 bool isNewBuf = true;
846
847 if (mRcvQueue.IsNull())
848 {
849 rcvBuf = System::PacketBufferHandle::New(kMaxReceiveMessageSize, 0);
850 }
851 else
852 {
853 rcvBuf = mRcvQueue->Last();
854 if (rcvBuf->AvailableDataLength() == 0)
855 {
856 rcvBuf = System::PacketBufferHandle::New(kMaxReceiveMessageSize, 0);
857 }
858 else
859 {
860 isNewBuf = false;
861 rcvBuf->CompactHead();
862 }
863 }
864
865 if (rcvBuf.IsNull())
866 {
867 DoClose(CHIP_ERROR_NO_MEMORY, false);
868 return;
869 }
870
871 // Attempt to receive data from the socket.
872 ssize_t rcvLen = recv(mSocket, rcvBuf->Start() + rcvBuf->DataLength(), rcvBuf->AvailableDataLength(), 0);
873
874#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
875 CHIP_ERROR err;
876 bool isProgressing = false;
877
878 err = CheckConnectionProgress(isProgressing);
879 if (err != CHIP_NO_ERROR)
880 {
881 DoClose(err, false);
882
883 return;
884 }
885
886 if (mLastTCPKernelSendQueueLen == 0)
887 {
888 // If the output queue has been flushed then stop the timer.
889
890 StopTCPUserTimeoutTimer();
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500891 }
892 else if (isProgressing && mUserTimeoutTimerRunning)
893 {
894 // Progress is being made. So, shift the timer
895 // forward if it was started.
896 RestartTCPUserTimeoutTimer();
897 }
898#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
899 // If an error occurred, abort the connection.
900 if (rcvLen < 0)
901 {
902 int systemErrno = errno;
903 if (systemErrno == EAGAIN)
904 {
905 // Note: in this case, we opt to not retry the recv call,
906 // and instead we expect that the read flags will get
907 // reset correctly upon a subsequent return from the
908 // select call.
909 ChipLogError(Inet, "recv: EAGAIN, will retry");
910
911 return;
912 }
913
914 DoClose(CHIP_ERROR_POSIX(systemErrno), false);
915 }
916
917 else
918 {
919 // Mark the connection as being active.
920 MarkActive();
921
922 // If the peer closed their end of the connection...
923 if (rcvLen == 0)
924 {
925 // If in the Connected state and the app has provided an OnPeerClose callback,
926 // enter the ReceiveShutdown state. Providing an OnPeerClose callback allows
927 // the app to decide whether to keep the send side of the connection open after
928 // the peer has closed. If no OnPeerClose is provided, we assume that the app
929 // wants to close both directions and automatically enter the Closing state.
930 if (mState == State::kConnected && OnPeerClose != nullptr)
931 {
932 mState = State::kReceiveShutdown;
933 }
934 else
935 {
936 mState = State::kClosing;
937 }
938 // Do not wait for ability to read on this endpoint.
939 (void) static_cast<System::LayerSockets &>(GetSystemLayer()).ClearCallbackOnPendingRead(mWatch);
940 // Call the app's OnPeerClose.
941 if (OnPeerClose != nullptr)
942 {
943 OnPeerClose(this);
944 }
945 }
946
947 // Otherwise, add the new data onto the receive queue.
948 else
949 {
950 VerifyOrDie(rcvLen > 0);
951 size_t newDataLength = rcvBuf->DataLength() + static_cast<size_t>(rcvLen);
952 VerifyOrDie(CanCastTo<uint16_t>(newDataLength));
953 if (isNewBuf)
954 {
955 rcvBuf->SetDataLength(static_cast<uint16_t>(newDataLength));
956 rcvBuf.RightSize();
957 if (mRcvQueue.IsNull())
958 {
959 mRcvQueue = std::move(rcvBuf);
960 }
961 else
962 {
963 mRcvQueue->AddToEnd(std::move(rcvBuf));
964 }
965 }
966 else
967 {
968 rcvBuf->SetDataLength(static_cast<uint16_t>(newDataLength), mRcvQueue);
969 }
970 }
971 }
972
973 // Drive any received data into the app.
974 DriveReceiving();
975}
976
977void TCPEndPointImplSockets::HandleIncomingConnection()
978{
979 CHIP_ERROR err = CHIP_NO_ERROR;
980 TCPEndPointImplSockets * conEP = nullptr;
981 IPAddress peerAddr;
982 uint16_t peerPort;
983
984 SockAddr sa;
985 memset(&sa, 0, sizeof(sa));
986 socklen_t saLen = sizeof(sa);
987
988 // Accept the new connection.
989 int conSocket = accept(mSocket, &sa.any, &saLen);
990 if (conSocket == -1)
991 {
992 if (errno == EAGAIN || errno == EWOULDBLOCK)
993 {
994 return;
995 }
Andrei Litvin0c438412022-03-16 14:30:08 -0400996
997 err = CHIP_ERROR_POSIX(errno);
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -0500998 }
999
1000 // If there's no callback available, fail with an error.
1001 if (err == CHIP_NO_ERROR && OnConnectionReceived == nullptr)
1002 {
1003 err = CHIP_ERROR_NO_CONNECTION_HANDLER;
1004 }
1005
1006 // Extract the peer's address information.
1007 if (err == CHIP_NO_ERROR)
1008 {
1009 if (sa.any.sa_family == AF_INET6)
1010 {
1011 peerAddr = IPAddress(sa.in6.sin6_addr);
1012 peerPort = ntohs(sa.in6.sin6_port);
1013 }
1014#if INET_CONFIG_ENABLE_IPV4
1015 else if (sa.any.sa_family == AF_INET)
1016 {
1017 peerAddr = IPAddress(sa.in.sin_addr);
1018 peerPort = ntohs(sa.in.sin_port);
1019 }
1020#endif // INET_CONFIG_ENABLE_IPV4
1021 else
1022 {
1023 err = CHIP_ERROR_INCORRECT_STATE;
1024 }
1025 }
1026
1027 // Attempt to allocate an end point object.
1028 if (err == CHIP_NO_ERROR)
1029 {
1030 TCPEndPoint * connectEndPoint = nullptr;
1031 err = GetEndPointManager().NewEndPoint(&connectEndPoint);
1032 conEP = static_cast<TCPEndPointImplSockets *>(connectEndPoint);
1033 }
1034
1035 // If all went well...
1036 if (err == CHIP_NO_ERROR)
1037 {
1038 // Put the new end point into the Connected state.
1039 conEP->mSocket = conSocket;
1040 err = static_cast<System::LayerSockets &>(GetSystemLayer()).StartWatchingSocket(conSocket, &conEP->mWatch);
1041 if (err == CHIP_NO_ERROR)
1042 {
1043 conEP->mState = State::kConnected;
1044#if INET_CONFIG_ENABLE_IPV4
1045 conEP->mAddrType = (sa.any.sa_family == AF_INET6) ? IPAddressType::kIPv6 : IPAddressType::kIPv4;
1046#else // !INET_CONFIG_ENABLE_IPV4
1047 conEP->mAddrType = IPAddressType::kIPv6;
1048#endif // !INET_CONFIG_ENABLE_IPV4
1049 conEP->Retain();
1050
1051 // Wait for ability to read on this endpoint.
1052 auto & conEPLayer = static_cast<System::LayerSockets &>(conEP->GetSystemLayer());
1053 err = conEPLayer.SetCallback(conEP->mWatch, HandlePendingIO, reinterpret_cast<intptr_t>(conEP));
1054 if (err == CHIP_NO_ERROR)
1055 {
1056 err = conEPLayer.RequestCallbackOnPendingRead(conEP->mWatch);
1057 }
1058 if (err == CHIP_NO_ERROR)
1059 {
1060 // Call the app's callback function.
1061 OnConnectionReceived(this, conEP, peerAddr, peerPort);
1062 return;
1063 }
1064 }
1065 }
1066
1067 // Otherwise immediately close the connection, clean up and call the app's error callback.
1068 if (conSocket != -1)
1069 {
1070 close(conSocket);
1071 }
1072 if (conEP != nullptr)
1073 {
1074 if (conEP->mState == State::kConnected)
1075 {
1076 conEP->Release();
1077 }
1078 conEP->Release();
1079 }
1080 if (OnAcceptError != nullptr)
1081 {
1082 OnAcceptError(this, err);
1083 }
1084}
1085
1086#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
1087/**
1088 * This function probes the TCP output queue and checks if data is successfully
1089 * being transferred to the other end.
1090 */
1091CHIP_ERROR TCPEndPointImplSockets::CheckConnectionProgress(bool & isProgressing)
1092{
1093 int currPendingBytesRaw = 0;
1094 uint32_t currPendingBytes; // Will be initialized once we know it's safe.
1095
1096 // Fetch the bytes pending successful transmission in the TCP out queue.
1097
Vivien Nicolas101ff172022-02-15 19:47:06 +01001098#ifdef __APPLE__
1099 socklen_t len = sizeof(currPendingBytesRaw);
1100 if (getsockopt(mSocket, SOL_SOCKET, SO_NWRITE, &currPendingBytesRaw, &len) < 0)
1101#else
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -05001102 if (ioctl(mSocket, TIOCOUTQ, &currPendingBytesRaw) < 0)
Vivien Nicolas101ff172022-02-15 19:47:06 +01001103#endif
Kevin Schoedelb9d8ef12021-12-08 03:24:49 -05001104 {
1105 return CHIP_ERROR_POSIX(errno);
1106 }
1107
1108 if (!CanCastTo<uint32_t>(currPendingBytesRaw))
1109 {
1110 return CHIP_ERROR_INCORRECT_STATE;
1111 }
1112
1113 currPendingBytes = static_cast<uint32_t>(currPendingBytesRaw);
1114
1115 if ((currPendingBytes != 0) && (mBytesWrittenSinceLastProbe + mLastTCPKernelSendQueueLen == currPendingBytes))
1116 {
1117 // No progress has been made
1118
1119 isProgressing = false;
1120 }
1121 else
1122 {
1123 // Data is flowing successfully
1124
1125 isProgressing = true;
1126 }
1127
1128 // Reset the value of the bytes written since the last probe into the tcp
1129 // outqueue was made and update the last tcp outqueue sample.
1130
1131 mBytesWrittenSinceLastProbe = 0;
1132
1133 mLastTCPKernelSendQueueLen = currPendingBytes;
1134
1135 return CHIP_NO_ERROR;
1136}
1137#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
1138
1139} // namespace Inet
1140} // namespace chip