Line data Source code
1 : /*
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 :
67 : namespace chip {
68 : namespace Inet {
69 :
70 15 : CHIP_ERROR TCPEndPointImplSockets::BindImpl(IPAddressType addrType, const IPAddress & addr, uint16_t port, bool reuseAddr)
71 : {
72 15 : CHIP_ERROR res = GetSocket(addrType);
73 :
74 15 : if (res == CHIP_NO_ERROR && reuseAddr)
75 : {
76 1 : int n = 1;
77 1 : 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
83 : // with TARGETED_LISTEN or TCP proxying services). Note that
84 : // one of the costs of this implementation is the
85 : // non-deterministic connection dispatch when multple clients
86 : // listen on the address with the same degreee of selectivity,
87 : // e.g. two untargetted-listen CHIP clients, or two
88 : // targeted-listen CHIP clients with the same node id.
89 :
90 1 : if (setsockopt(mSocket, SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n)) != 0)
91 : {
92 0 : ChipLogError(Inet, "SO_REUSEPORT: %d", errno);
93 : }
94 : #endif // defined(SO_REUSEPORT)
95 : }
96 :
97 15 : if (res == CHIP_NO_ERROR)
98 : {
99 : SockAddr sa;
100 14 : memset(&sa, 0, sizeof(sa));
101 14 : socklen_t sockaddrsize = 0;
102 :
103 14 : if (addrType == IPAddressType::kIPv6)
104 : {
105 9 : sa.in6.sin6_family = AF_INET6;
106 9 : sa.in6.sin6_port = htons(port);
107 9 : sa.in6.sin6_flowinfo = 0;
108 9 : sa.in6.sin6_addr = addr.ToIPv6();
109 9 : sa.in6.sin6_scope_id = 0;
110 :
111 9 : sockaddrsize = sizeof(sa.in6);
112 : }
113 : #if INET_CONFIG_ENABLE_IPV4
114 5 : else if (addrType == IPAddressType::kIPv4)
115 : {
116 5 : sa.in.sin_family = AF_INET;
117 5 : sa.in.sin_port = htons(port);
118 5 : sa.in.sin_addr = addr.ToIPv4();
119 :
120 5 : sockaddrsize = sizeof(sa.in);
121 : }
122 : #endif // INET_CONFIG_ENABLE_IPV4
123 : else
124 : {
125 0 : res = INET_ERROR_WRONG_ADDRESS_TYPE;
126 : }
127 :
128 14 : if (res == CHIP_NO_ERROR)
129 : {
130 : // NOLINTNEXTLINE(clang-analyzer-unix.StdCLibraryFunctions): GetSocket calls ensure mSocket is valid
131 14 : if (bind(mSocket, &sa.any, sockaddrsize) != 0)
132 : {
133 0 : res = CHIP_ERROR_POSIX(errno);
134 : }
135 : }
136 : }
137 :
138 15 : return res;
139 : }
140 :
141 14 : CHIP_ERROR TCPEndPointImplSockets::ListenImpl(uint16_t backlog)
142 : {
143 14 : if (listen(mSocket, backlog) != 0)
144 : {
145 0 : return CHIP_ERROR_POSIX(errno);
146 : }
147 :
148 : // Enable non-blocking mode for the socket.
149 14 : int flags = fcntl(mSocket, F_GETFL, 0);
150 14 : fcntl(mSocket, F_SETFL, flags | O_NONBLOCK);
151 :
152 : // Wait for ability to read on this endpoint.
153 14 : CHIP_ERROR res = static_cast<System::LayerSockets &>(GetSystemLayer())
154 14 : .SetCallback(mWatch, HandlePendingIO, reinterpret_cast<intptr_t>(this));
155 14 : if (res == CHIP_NO_ERROR)
156 : {
157 14 : res = static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingRead(mWatch);
158 : }
159 :
160 14 : return res;
161 : }
162 :
163 10 : CHIP_ERROR TCPEndPointImplSockets::ConnectImpl(const IPAddress & addr, uint16_t port, InterfaceId intfId)
164 : {
165 10 : IPAddressType addrType = addr.Type();
166 :
167 10 : ReturnErrorOnFailure(GetSocket(addrType));
168 :
169 10 : if (!intfId.IsPresent())
170 : {
171 : // The behavior when connecting to an IPv6 link-local address without specifying an outbound
172 : // interface is ambiguous. So prevent it in all cases.
173 10 : if (addr.IsIPv6LinkLocal())
174 : {
175 0 : return INET_ERROR_WRONG_ADDRESS_TYPE;
176 : }
177 : }
178 : else
179 : {
180 : // Try binding to the interface
181 :
182 : // If destination is link-local then there is no need to bind to
183 : // interface or address on the interface.
184 :
185 0 : if (!addr.IsIPv6LinkLocal())
186 : {
187 : #ifdef SO_BINDTODEVICE
188 : struct ::ifreq ifr;
189 0 : memset(&ifr, 0, sizeof(ifr));
190 :
191 0 : ReturnErrorOnFailure(intfId.GetInterfaceName(ifr.ifr_name, sizeof(ifr.ifr_name)));
192 :
193 : // Attempt to bind to the interface using SO_BINDTODEVICE which requires privileged access.
194 : // If the permission is denied(EACCES) because CHIP is running in a context
195 : // that does not have privileged access, choose a source address on the
196 : // interface to bind the connetion to.
197 0 : int r = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
198 0 : if (r < 0 && errno != EACCES)
199 : {
200 0 : return CHIP_ERROR_POSIX(errno);
201 : }
202 :
203 0 : if (r < 0)
204 : #endif // SO_BINDTODEVICE
205 : {
206 : // Attempting to initiate a connection via a specific interface is not allowed.
207 : // The only way to do this is to bind the local to an address on the desired
208 : // interface.
209 0 : ReturnErrorOnFailure(BindSrcAddrFromIntf(addrType, intfId));
210 : }
211 : }
212 : }
213 :
214 : // Disable generation of SIGPIPE.
215 : #ifdef SO_NOSIGPIPE
216 : int n = 1;
217 : setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &n, sizeof(n));
218 : #endif // defined(SO_NOSIGPIPE)
219 :
220 : // Enable non-blocking mode for the socket.
221 10 : int flags = fcntl(mSocket, F_GETFL, 0);
222 10 : fcntl(mSocket, F_SETFL, flags | O_NONBLOCK);
223 :
224 10 : socklen_t sockaddrsize = 0;
225 :
226 : SockAddr sa;
227 10 : memset(&sa, 0, sizeof(sa));
228 :
229 10 : if (addrType == IPAddressType::kIPv6)
230 : {
231 6 : sa.in6.sin6_family = AF_INET6;
232 6 : sa.in6.sin6_port = htons(port);
233 6 : sa.in6.sin6_flowinfo = 0;
234 6 : sa.in6.sin6_addr = addr.ToIPv6();
235 6 : sa.in6.sin6_scope_id = intfId.GetPlatformInterface();
236 6 : sockaddrsize = sizeof(sockaddr_in6);
237 : }
238 : #if INET_CONFIG_ENABLE_IPV4
239 4 : else if (addrType == IPAddressType::kIPv4)
240 : {
241 4 : sa.in.sin_family = AF_INET;
242 4 : sa.in.sin_port = htons(port);
243 4 : sa.in.sin_addr = addr.ToIPv4();
244 4 : sockaddrsize = sizeof(sockaddr_in);
245 : }
246 : #endif // INET_CONFIG_ENABLE_IPV4
247 : else
248 : {
249 0 : return INET_ERROR_WRONG_ADDRESS_TYPE;
250 : }
251 :
252 : // NOLINTNEXTLINE(clang-analyzer-unix.StdCLibraryFunctions): GetSocket calls ensure mSocket is valid
253 10 : int conRes = connect(mSocket, &sa.any, sockaddrsize);
254 :
255 10 : if (conRes == -1 && errno != EINPROGRESS)
256 : {
257 0 : CHIP_ERROR res = CHIP_ERROR_POSIX(errno);
258 0 : DoClose(res, true);
259 0 : return res;
260 : }
261 :
262 10 : ReturnErrorOnFailure(static_cast<System::LayerSockets &>(GetSystemLayer())
263 : .SetCallback(mWatch, HandlePendingIO, reinterpret_cast<intptr_t>(this)));
264 :
265 : // Once Connecting or Connected, bump the reference count. The corresponding Release() will happen in DoClose().
266 10 : Retain();
267 :
268 10 : if (conRes == 0)
269 : {
270 0 : mState = State::kConnected;
271 : // Wait for ability to read on this endpoint.
272 0 : ReturnErrorOnFailure(static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingRead(mWatch));
273 0 : if (OnConnectComplete != nullptr)
274 : {
275 0 : OnConnectComplete(this, CHIP_NO_ERROR);
276 : }
277 : }
278 : else
279 : {
280 10 : mState = State::kConnecting;
281 : // Wait for ability to write on this endpoint.
282 10 : ReturnErrorOnFailure(static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingWrite(mWatch));
283 : }
284 :
285 10 : return CHIP_NO_ERROR;
286 : }
287 :
288 29 : CHIP_ERROR TCPEndPointImplSockets::GetPeerInfo(IPAddress * retAddr, uint16_t * retPort) const
289 : {
290 29 : return GetSocketInfo(getpeername, retAddr, retPort);
291 : }
292 :
293 1 : CHIP_ERROR TCPEndPointImplSockets::GetLocalInfo(IPAddress * retAddr, uint16_t * retPort) const
294 : {
295 1 : return GetSocketInfo(getsockname, retAddr, retPort);
296 : }
297 :
298 30 : CHIP_ERROR TCPEndPointImplSockets::GetSocketInfo(int getname(int, sockaddr *, socklen_t *), IPAddress * retAddr,
299 : uint16_t * retPort) const
300 : {
301 30 : VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
302 :
303 : SockAddr sa;
304 28 : memset(&sa, 0, sizeof(sa));
305 28 : socklen_t saLen = sizeof(sa);
306 :
307 28 : if (getname(mSocket, &sa.any, &saLen) != 0)
308 : {
309 0 : return CHIP_ERROR_POSIX(errno);
310 : }
311 :
312 28 : if (sa.any.sa_family == AF_INET6)
313 : {
314 17 : *retAddr = IPAddress(sa.in6.sin6_addr);
315 17 : *retPort = ntohs(sa.in6.sin6_port);
316 17 : return CHIP_NO_ERROR;
317 : }
318 :
319 : #if INET_CONFIG_ENABLE_IPV4
320 11 : if (sa.any.sa_family == AF_INET)
321 : {
322 11 : *retAddr = IPAddress(sa.in.sin_addr);
323 11 : *retPort = ntohs(sa.in.sin_port);
324 11 : return CHIP_NO_ERROR;
325 : }
326 : #endif // INET_CONFIG_ENABLE_IPV4
327 :
328 0 : return CHIP_ERROR_INCORRECT_STATE;
329 : }
330 :
331 25 : CHIP_ERROR TCPEndPointImplSockets::GetInterfaceId(InterfaceId * retInterface)
332 : {
333 25 : VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
334 :
335 : SockAddr sa;
336 25 : memset(&sa, 0, sizeof(sa));
337 25 : socklen_t saLen = sizeof(sa);
338 :
339 25 : if (getpeername(mSocket, &sa.any, &saLen) != 0)
340 : {
341 0 : return CHIP_ERROR_POSIX(errno);
342 : }
343 :
344 25 : if (sa.any.sa_family == AF_INET6)
345 : {
346 15 : if (IPAddress(sa.in6.sin6_addr).IsIPv6LinkLocal())
347 : {
348 0 : *retInterface = InterfaceId(sa.in6.sin6_scope_id);
349 : }
350 : else
351 : {
352 : // TODO: Is there still a meaningful interface id in this case?
353 15 : *retInterface = InterfaceId::Null();
354 : }
355 15 : return CHIP_NO_ERROR;
356 : }
357 :
358 : #if INET_CONFIG_ENABLE_IPV4
359 10 : if (sa.any.sa_family == AF_INET)
360 : {
361 : // No interface id available for IPv4 sockets.
362 10 : *retInterface = InterfaceId::Null();
363 10 : return CHIP_NO_ERROR;
364 : }
365 : #endif // INET_CONFIG_ENABLE_IPV4
366 :
367 0 : *retInterface = InterfaceId::Null();
368 0 : return INET_ERROR_WRONG_ADDRESS_TYPE;
369 : }
370 :
371 5 : CHIP_ERROR TCPEndPointImplSockets::SendQueuedImpl(bool queueWasEmpty)
372 : {
373 5 : if (queueWasEmpty)
374 : {
375 : // Wait for ability to write on this endpoint.
376 5 : return static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingWrite(mWatch);
377 : }
378 0 : return CHIP_NO_ERROR;
379 : }
380 :
381 20 : CHIP_ERROR TCPEndPointImplSockets::EnableNoDelay()
382 : {
383 20 : VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
384 :
385 : #ifdef TCP_NODELAY
386 : // Disable TCP Nagle buffering by setting TCP_NODELAY socket option to true
387 20 : int val = 1;
388 20 : if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_NODELAY, &val, sizeof(val)) != 0)
389 : {
390 0 : return CHIP_ERROR_POSIX(errno);
391 : }
392 : #endif // defined(TCP_NODELAY)
393 :
394 20 : return CHIP_NO_ERROR;
395 : }
396 :
397 21 : CHIP_ERROR TCPEndPointImplSockets::EnableKeepAlive(uint16_t interval, uint16_t timeoutCount)
398 : {
399 21 : VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
400 :
401 : // Set the idle interval
402 20 : int val = interval;
403 20 : if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_IDLE_INTERVAL_OPT_NAME, &val, sizeof(val)) != 0)
404 : {
405 0 : return CHIP_ERROR_POSIX(errno);
406 : }
407 :
408 : // Set the probe retransmission interval.
409 20 : val = interval;
410 20 : if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_KEEPINTVL, &val, sizeof(val)) != 0)
411 : {
412 0 : return CHIP_ERROR_POSIX(errno);
413 : }
414 :
415 : // Set the probe timeout count
416 20 : val = timeoutCount;
417 20 : if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_KEEPCNT, &val, sizeof(val)) != 0)
418 : {
419 0 : return CHIP_ERROR_POSIX(errno);
420 : }
421 :
422 : // Enable keepalives for the connection.
423 20 : val = 1; // enable
424 20 : if (setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0)
425 : {
426 0 : return CHIP_ERROR_POSIX(errno);
427 : }
428 :
429 20 : return CHIP_NO_ERROR;
430 : }
431 :
432 1 : CHIP_ERROR TCPEndPointImplSockets::DisableKeepAlive()
433 : {
434 1 : VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
435 :
436 : // Disable keepalives on the connection.
437 0 : int val = 0; // disable
438 0 : if (setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0)
439 : {
440 0 : return CHIP_ERROR_POSIX(errno);
441 : }
442 :
443 0 : return CHIP_NO_ERROR;
444 : }
445 :
446 6 : CHIP_ERROR TCPEndPointImplSockets::AckReceive(size_t len)
447 : {
448 6 : VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
449 :
450 : // nothing to do for sockets case
451 5 : return CHIP_NO_ERROR;
452 : }
453 :
454 0 : CHIP_ERROR TCPEndPointImplSockets::SetUserTimeoutImpl(uint32_t userTimeoutMillis)
455 : {
456 : #if defined(TCP_USER_TIMEOUT)
457 : // Set the user timeout
458 0 : uint32_t val = userTimeoutMillis;
459 0 : if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_USER_TIMEOUT, &val, sizeof(val)) != 0)
460 : {
461 0 : return CHIP_ERROR_POSIX(errno);
462 : }
463 0 : return CHIP_NO_ERROR;
464 : #else // TCP_USER_TIMEOUT
465 : return CHIP_ERROR_NOT_IMPLEMENTED;
466 : #endif // defined(TCP_USER_TIMEOUT)
467 : }
468 :
469 5 : CHIP_ERROR TCPEndPointImplSockets::DriveSendingImpl()
470 : {
471 5 : CHIP_ERROR err = CHIP_NO_ERROR;
472 :
473 : #ifdef MSG_NOSIGNAL
474 5 : const int sendFlags = MSG_NOSIGNAL;
475 : #else
476 : const int sendFlags = 0;
477 : #endif
478 :
479 : // Pretend send() fails in the while loop below
480 5 : INET_FAULT_INJECT(FaultInjection::kFault_Send, {
481 : err = CHIP_ERROR_POSIX(EIO);
482 : DoClose(err, false);
483 : return err;
484 : });
485 :
486 10 : while (!mSendQueue.IsNull())
487 : {
488 5 : size_t bufLen = mSendQueue->DataLength();
489 :
490 5 : ssize_t lenSentRaw = send(mSocket, mSendQueue->Start(), bufLen, sendFlags);
491 :
492 5 : if (lenSentRaw == -1)
493 : {
494 0 : if (errno != EAGAIN && errno != EWOULDBLOCK)
495 : {
496 0 : err = (errno == EPIPE) ? INET_ERROR_PEER_DISCONNECTED : CHIP_ERROR_POSIX(errno);
497 : }
498 0 : break;
499 : }
500 :
501 5 : if (lenSentRaw < 0 || bufLen < static_cast<size_t>(lenSentRaw))
502 : {
503 0 : err = CHIP_ERROR_INCORRECT_STATE;
504 0 : break;
505 : }
506 :
507 5 : size_t lenSent = static_cast<size_t>(lenSentRaw);
508 :
509 : // Mark the connection as being active.
510 5 : MarkActive();
511 :
512 5 : if (lenSent < bufLen)
513 : {
514 0 : mSendQueue->ConsumeHead(lenSent);
515 : }
516 : else
517 : {
518 5 : mSendQueue.FreeHead();
519 5 : if (mSendQueue.IsNull())
520 : {
521 : // Do not wait for ability to write on this endpoint.
522 5 : err = static_cast<System::LayerSockets &>(GetSystemLayer()).ClearCallbackOnPendingWrite(mWatch);
523 5 : if (err != CHIP_NO_ERROR)
524 : {
525 0 : break;
526 : }
527 : }
528 : }
529 :
530 5 : if (OnDataSent != nullptr)
531 : {
532 0 : OnDataSent(this, lenSent);
533 : }
534 :
535 : #if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
536 5 : mBytesWrittenSinceLastProbe += lenSent;
537 :
538 5 : bool isProgressing = false;
539 :
540 5 : err = CheckConnectionProgress(isProgressing);
541 5 : if (err != CHIP_NO_ERROR)
542 : {
543 0 : break;
544 : }
545 :
546 5 : if (!mUserTimeoutTimerRunning)
547 : {
548 : // Timer was not running before this write. So, start
549 : // the timer.
550 :
551 5 : StartTCPUserTimeoutTimer();
552 : }
553 0 : else if (isProgressing)
554 : {
555 : // Progress is being made. So, shift the timer
556 : // forward if it was started.
557 :
558 0 : RestartTCPUserTimeoutTimer();
559 : }
560 : #endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
561 :
562 5 : if (lenSent < bufLen)
563 : {
564 0 : break;
565 : }
566 : }
567 :
568 5 : 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 5 : if (mState == State::kSendShutdown && mSendQueue.IsNull())
572 : {
573 0 : if (shutdown(mSocket, SHUT_WR) != 0)
574 : {
575 0 : err = CHIP_ERROR_POSIX(errno);
576 : }
577 : }
578 : }
579 :
580 5 : return err;
581 : }
582 :
583 10 : void TCPEndPointImplSockets::HandleConnectCompleteImpl()
584 : {
585 : // Wait for ability to read or write on this endpoint.
586 10 : CHIP_ERROR err = static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingRead(mWatch);
587 10 : if (err == CHIP_NO_ERROR)
588 : {
589 10 : err = static_cast<System::LayerSockets &>(GetSystemLayer()).RequestCallbackOnPendingWrite(mWatch);
590 : }
591 10 : if (err != CHIP_NO_ERROR)
592 : {
593 0 : DoClose(err, false);
594 0 : return;
595 : }
596 : }
597 :
598 34 : void TCPEndPointImplSockets::DoCloseImpl(CHIP_ERROR err, State oldState)
599 : {
600 : struct linger lingerStruct;
601 :
602 : // If the socket hasn't been closed already...
603 34 : 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 34 : if (mState == State::kClosed || (mState == State::kClosing && mSendQueue.IsNull()))
609 : {
610 : // If aborting the connection, ensure we send a TCP RST.
611 34 : if (IsConnected(oldState) && err != CHIP_NO_ERROR)
612 : {
613 1 : lingerStruct.l_onoff = 1;
614 1 : lingerStruct.l_linger = 0;
615 :
616 1 : if (setsockopt(mSocket, SOL_SOCKET, SO_LINGER, &lingerStruct, sizeof(lingerStruct)) != 0)
617 : {
618 0 : ChipLogError(Inet, "SO_LINGER: %d", errno);
619 : }
620 : }
621 :
622 34 : static_cast<System::LayerSockets &>(GetSystemLayer()).StopWatchingSocket(&mWatch);
623 34 : close(mSocket);
624 34 : mSocket = kInvalidSocketFd;
625 : }
626 : }
627 34 : }
628 :
629 : #if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
630 0 : void TCPEndPointImplSockets::TCPUserTimeoutHandler()
631 : {
632 : // Set the timer running flag to false
633 0 : mUserTimeoutTimerRunning = false;
634 :
635 0 : bool isProgressing = false;
636 0 : CHIP_ERROR err = CheckConnectionProgress(isProgressing);
637 :
638 0 : if (err == CHIP_NO_ERROR && mLastTCPKernelSendQueueLen != 0)
639 : {
640 : // There is data in the TCP Send Queue
641 0 : 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 0 : StartTCPUserTimeoutTimer();
648 : }
649 : else
650 : {
651 : // Close the connection as the TCP UserTimeout has expired
652 0 : err = INET_ERROR_TCP_USER_TIMEOUT;
653 : }
654 : }
655 :
656 0 : if (err != CHIP_NO_ERROR)
657 : {
658 : // Close the connection as the TCP UserTimeout has expired
659 0 : DoClose(err, false);
660 : }
661 0 : }
662 : #endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
663 :
664 0 : CHIP_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 0 : VerifyOrReturnError(mState != State::kBound, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
672 :
673 0 : bool ipAddrFound = false;
674 0 : for (InterfaceAddressIterator addrIter; addrIter.HasCurrent(); addrIter.Next())
675 : {
676 : IPAddress curAddr;
677 0 : if ((addrIter.GetInterfaceId() == intfId) && (addrIter.GetAddress(curAddr) == CHIP_NO_ERROR))
678 : {
679 : // Search for an IPv4 address on the TargetInterface
680 :
681 : #if INET_CONFIG_ENABLE_IPV4
682 0 : if (addrType == IPAddressType::kIPv4)
683 : {
684 0 : if (curAddr.IsIPv4())
685 : {
686 : // Bind to the IPv4 address of the TargetInterface
687 0 : ipAddrFound = true;
688 0 : ReturnErrorOnFailure(Bind(IPAddressType::kIPv4, curAddr, 0, true));
689 :
690 0 : break;
691 : }
692 : }
693 : #endif // INET_CONFIG_ENABLE_IPV4
694 0 : 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 0 : if (!curAddr.IsIPv4() && !curAddr.IsIPv6LinkLocal() && !curAddr.IsMulticast())
700 : {
701 : // Bind to the IPv6 address of the TargetInterface
702 0 : ipAddrFound = true;
703 0 : ReturnErrorOnFailure(Bind(IPAddressType::kIPv6, curAddr, 0, true));
704 :
705 0 : break;
706 : }
707 : }
708 : }
709 0 : }
710 :
711 0 : VerifyOrReturnError(ipAddrFound, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
712 :
713 0 : return CHIP_NO_ERROR;
714 : }
715 :
716 25 : CHIP_ERROR TCPEndPointImplSockets::GetSocket(IPAddressType addrType)
717 : {
718 25 : if (mSocket == kInvalidSocketFd)
719 : {
720 : int family;
721 25 : if (addrType == IPAddressType::kIPv6)
722 : {
723 15 : family = PF_INET6;
724 : #if INET_CONFIG_ENABLE_IPV4
725 : }
726 10 : else if (addrType == IPAddressType::kIPv4)
727 : {
728 9 : family = PF_INET;
729 : #endif // INET_CONFIG_ENABLE_IPV4
730 : }
731 : else
732 : {
733 1 : return INET_ERROR_WRONG_ADDRESS_TYPE;
734 : }
735 24 : mSocket = ::socket(family, SOCK_STREAM | SOCK_CLOEXEC, 0);
736 24 : if (mSocket == -1)
737 : {
738 0 : return CHIP_ERROR_POSIX(errno);
739 : }
740 24 : ReturnErrorOnFailure(static_cast<System::LayerSockets &>(GetSystemLayer()).StartWatchingSocket(mSocket, &mWatch));
741 24 : 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 24 : if (family == PF_INET6)
747 : {
748 15 : int one = 1;
749 15 : 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 0 : else if (mAddrType != addrType)
767 : {
768 0 : return CHIP_ERROR_INCORRECT_STATE;
769 : }
770 :
771 24 : return CHIP_NO_ERROR;
772 : }
773 :
774 : // static
775 34 : void TCPEndPointImplSockets::HandlePendingIO(System::SocketEvents events, intptr_t data)
776 : {
777 34 : reinterpret_cast<TCPEndPointImplSockets *>(data)->HandlePendingIO(events);
778 34 : }
779 :
780 34 : void TCPEndPointImplSockets::HandlePendingIO(System::SocketEvents events)
781 : {
782 : // Prevent the end point from being freed while in the middle of a callback.
783 34 : 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 34 : if (mState == State::kListening)
788 : {
789 10 : if (OnConnectionReceived != nullptr && events.Has(System::SocketEventFlags::kRead))
790 : {
791 10 : HandleIncomingConnection();
792 : }
793 : }
794 :
795 : // If in the processes of initiating a connection...
796 24 : else if (mState == State::kConnecting)
797 : {
798 : // The socket being writable indicates the connection has completed (successfully or otherwise).
799 10 : if (events.Has(System::SocketEventFlags::kWrite))
800 : {
801 : #ifndef __MBED__
802 : // Get the connection result from the socket.
803 : int osConRes;
804 10 : socklen_t optLen = sizeof(osConRes);
805 10 : if (getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &osConRes, &optLen) != 0)
806 : {
807 0 : osConRes = errno;
808 : }
809 : #else // __MBED__
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 // !__MBED__
814 10 : CHIP_ERROR conRes = CHIP_ERROR_POSIX(osConRes);
815 :
816 : // Process the connection result.
817 10 : 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 14 : if (IsConnected() && !mSendQueue.IsNull() && events.Has(System::SocketEventFlags::kWrite))
826 : {
827 0 : 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 28 : if ((mState == State::kConnected || mState == State::kSendShutdown) && mReceiveEnabled && OnDataReceived != nullptr &&
833 14 : events.Has(System::SocketEventFlags::kRead))
834 : {
835 14 : ReceiveData();
836 : }
837 : }
838 :
839 34 : Release();
840 34 : }
841 :
842 14 : void TCPEndPointImplSockets::ReceiveData()
843 : {
844 14 : System::PacketBufferHandle rcvBuf;
845 14 : bool isNewBuf = true;
846 :
847 14 : if (mRcvQueue.IsNull())
848 : {
849 14 : rcvBuf = System::PacketBufferHandle::New(kMaxReceiveMessageSize, 0);
850 : }
851 : else
852 : {
853 0 : rcvBuf = mRcvQueue->Last();
854 0 : if (rcvBuf->AvailableDataLength() == 0)
855 : {
856 0 : rcvBuf = System::PacketBufferHandle::New(kMaxReceiveMessageSize, 0);
857 : }
858 : else
859 : {
860 0 : isNewBuf = false;
861 0 : rcvBuf->CompactHead();
862 : }
863 : }
864 :
865 14 : if (rcvBuf.IsNull())
866 : {
867 0 : DoClose(CHIP_ERROR_NO_MEMORY, false);
868 0 : return;
869 : }
870 :
871 : // Attempt to receive data from the socket.
872 14 : 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 14 : bool isProgressing = false;
877 :
878 14 : err = CheckConnectionProgress(isProgressing);
879 14 : if (err != CHIP_NO_ERROR)
880 : {
881 0 : DoClose(err, false);
882 :
883 0 : return;
884 : }
885 :
886 14 : if (mLastTCPKernelSendQueueLen == 0)
887 : {
888 : // If the output queue has been flushed then stop the timer.
889 :
890 14 : StopTCPUserTimeoutTimer();
891 : }
892 0 : else if (isProgressing && mUserTimeoutTimerRunning)
893 : {
894 : // Progress is being made. So, shift the timer
895 : // forward if it was started.
896 0 : RestartTCPUserTimeoutTimer();
897 : }
898 : #endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
899 : // If an error occurred, abort the connection.
900 14 : if (rcvLen < 0)
901 : {
902 0 : int systemErrno = errno;
903 0 : 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 0 : ChipLogError(Inet, "recv: EAGAIN, will retry");
910 :
911 0 : return;
912 : }
913 :
914 0 : DoClose(CHIP_ERROR_POSIX(systemErrno), false);
915 : }
916 :
917 : else
918 : {
919 : // Mark the connection as being active.
920 14 : MarkActive();
921 :
922 : // If the peer closed their end of the connection...
923 14 : 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 9 : if (mState == State::kConnected && OnPeerClose != nullptr)
931 : {
932 0 : mState = State::kReceiveShutdown;
933 : }
934 : else
935 : {
936 9 : mState = State::kClosing;
937 : }
938 : // Do not wait for ability to read on this endpoint.
939 9 : (void) static_cast<System::LayerSockets &>(GetSystemLayer()).ClearCallbackOnPendingRead(mWatch);
940 : // Call the app's OnPeerClose.
941 9 : if (OnPeerClose != nullptr)
942 : {
943 0 : OnPeerClose(this);
944 : }
945 : }
946 :
947 : // Otherwise, add the new data onto the receive queue.
948 : else
949 : {
950 5 : VerifyOrDie(rcvLen > 0);
951 5 : size_t newDataLength = rcvBuf->DataLength() + static_cast<size_t>(rcvLen);
952 5 : if (isNewBuf)
953 : {
954 5 : rcvBuf->SetDataLength(newDataLength);
955 5 : rcvBuf.RightSize();
956 5 : if (mRcvQueue.IsNull())
957 : {
958 5 : mRcvQueue = std::move(rcvBuf);
959 : }
960 : else
961 : {
962 0 : mRcvQueue->AddToEnd(std::move(rcvBuf));
963 : }
964 : }
965 : else
966 : {
967 0 : rcvBuf->SetDataLength(newDataLength, mRcvQueue);
968 : }
969 : }
970 : }
971 :
972 : // Drive any received data into the app.
973 14 : DriveReceiving();
974 14 : }
975 :
976 10 : void TCPEndPointImplSockets::HandleIncomingConnection()
977 : {
978 10 : CHIP_ERROR err = CHIP_NO_ERROR;
979 10 : TCPEndPointImplSockets * conEP = nullptr;
980 : IPAddress peerAddr;
981 : uint16_t peerPort;
982 :
983 : SockAddr sa;
984 10 : memset(&sa, 0, sizeof(sa));
985 10 : socklen_t saLen = sizeof(sa);
986 :
987 : // Accept the new connection.
988 10 : int conSocket = accept(mSocket, &sa.any, &saLen);
989 10 : if (conSocket == -1)
990 : {
991 0 : if (errno == EAGAIN || errno == EWOULDBLOCK)
992 : {
993 10 : return;
994 : }
995 :
996 0 : err = CHIP_ERROR_POSIX(errno);
997 : }
998 :
999 : // If there's no callback available, fail with an error.
1000 10 : if (err == CHIP_NO_ERROR && OnConnectionReceived == nullptr)
1001 : {
1002 0 : err = CHIP_ERROR_NO_CONNECTION_HANDLER;
1003 : }
1004 :
1005 : // Extract the peer's address information.
1006 10 : if (err == CHIP_NO_ERROR)
1007 : {
1008 10 : if (sa.any.sa_family == AF_INET6)
1009 : {
1010 6 : peerAddr = IPAddress(sa.in6.sin6_addr);
1011 6 : peerPort = ntohs(sa.in6.sin6_port);
1012 : }
1013 : #if INET_CONFIG_ENABLE_IPV4
1014 4 : else if (sa.any.sa_family == AF_INET)
1015 : {
1016 4 : peerAddr = IPAddress(sa.in.sin_addr);
1017 4 : peerPort = ntohs(sa.in.sin_port);
1018 : }
1019 : #endif // INET_CONFIG_ENABLE_IPV4
1020 : else
1021 : {
1022 0 : err = CHIP_ERROR_INCORRECT_STATE;
1023 : }
1024 : }
1025 :
1026 : // Attempt to allocate an end point object.
1027 10 : if (err == CHIP_NO_ERROR)
1028 : {
1029 10 : TCPEndPoint * connectEndPoint = nullptr;
1030 10 : err = GetEndPointManager().NewEndPoint(&connectEndPoint);
1031 10 : conEP = static_cast<TCPEndPointImplSockets *>(connectEndPoint);
1032 : }
1033 :
1034 : // If all went well...
1035 10 : if (err == CHIP_NO_ERROR)
1036 : {
1037 : // Put the new end point into the Connected state.
1038 10 : conEP->mSocket = conSocket;
1039 10 : err = static_cast<System::LayerSockets &>(GetSystemLayer()).StartWatchingSocket(conSocket, &conEP->mWatch);
1040 10 : if (err == CHIP_NO_ERROR)
1041 : {
1042 10 : conEP->mState = State::kConnected;
1043 : #if INET_CONFIG_ENABLE_IPV4
1044 10 : conEP->mAddrType = (sa.any.sa_family == AF_INET6) ? IPAddressType::kIPv6 : IPAddressType::kIPv4;
1045 : #else // !INET_CONFIG_ENABLE_IPV4
1046 : conEP->mAddrType = IPAddressType::kIPv6;
1047 : #endif // !INET_CONFIG_ENABLE_IPV4
1048 10 : conEP->Retain();
1049 :
1050 : // Wait for ability to read on this endpoint.
1051 10 : auto & conEPLayer = static_cast<System::LayerSockets &>(conEP->GetSystemLayer());
1052 10 : err = conEPLayer.SetCallback(conEP->mWatch, HandlePendingIO, reinterpret_cast<intptr_t>(conEP));
1053 10 : if (err == CHIP_NO_ERROR)
1054 : {
1055 10 : err = conEPLayer.RequestCallbackOnPendingRead(conEP->mWatch);
1056 : }
1057 10 : if (err == CHIP_NO_ERROR)
1058 : {
1059 : // Call the app's callback function.
1060 10 : OnConnectionReceived(this, conEP, peerAddr, peerPort);
1061 10 : return;
1062 : }
1063 : }
1064 : }
1065 :
1066 : // Otherwise immediately close the connection, clean up and call the app's error callback.
1067 0 : if (conSocket != -1)
1068 : {
1069 0 : close(conSocket);
1070 : }
1071 0 : if (conEP != nullptr)
1072 : {
1073 0 : if (conEP->mState == State::kConnected)
1074 : {
1075 0 : conEP->Release();
1076 : }
1077 0 : conEP->Release();
1078 : }
1079 0 : if (OnAcceptError != nullptr)
1080 : {
1081 0 : OnAcceptError(this, err);
1082 : }
1083 : }
1084 :
1085 : #if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
1086 : /**
1087 : * This function probes the TCP output queue and checks if data is successfully
1088 : * being transferred to the other end.
1089 : */
1090 19 : CHIP_ERROR TCPEndPointImplSockets::CheckConnectionProgress(bool & isProgressing)
1091 : {
1092 19 : int currPendingBytesRaw = 0;
1093 : uint32_t currPendingBytes; // Will be initialized once we know it's safe.
1094 :
1095 : // Fetch the bytes pending successful transmission in the TCP out queue.
1096 :
1097 : #ifdef __APPLE__
1098 : socklen_t len = sizeof(currPendingBytesRaw);
1099 : if (getsockopt(mSocket, SOL_SOCKET, SO_NWRITE, &currPendingBytesRaw, &len) < 0)
1100 : #else
1101 19 : if (ioctl(mSocket, TIOCOUTQ, &currPendingBytesRaw) < 0)
1102 : #endif
1103 : {
1104 0 : return CHIP_ERROR_POSIX(errno);
1105 : }
1106 :
1107 19 : if (!CanCastTo<uint32_t>(currPendingBytesRaw))
1108 : {
1109 0 : return CHIP_ERROR_INCORRECT_STATE;
1110 : }
1111 :
1112 19 : currPendingBytes = static_cast<uint32_t>(currPendingBytesRaw);
1113 :
1114 19 : if ((currPendingBytes != 0) && (mBytesWrittenSinceLastProbe + mLastTCPKernelSendQueueLen == currPendingBytes))
1115 : {
1116 : // No progress has been made
1117 :
1118 0 : isProgressing = false;
1119 : }
1120 : else
1121 : {
1122 : // Data is flowing successfully
1123 :
1124 19 : isProgressing = true;
1125 : }
1126 :
1127 : // Reset the value of the bytes written since the last probe into the tcp
1128 : // outqueue was made and update the last tcp outqueue sample.
1129 :
1130 19 : mBytesWrittenSinceLastProbe = 0;
1131 :
1132 19 : mLastTCPKernelSendQueueLen = currPendingBytes;
1133 :
1134 19 : return CHIP_NO_ERROR;
1135 : }
1136 : #endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
1137 :
1138 : } // namespace Inet
1139 : } // namespace chip
|