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