| /* |
| * |
| * Copyright (c) 2020 Project CHIP Authors |
| * Copyright (c) 2013-2017 Nest Labs, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @file |
| * This file defines classes for abstracting access to and |
| * interactions with a platform- and system-specific Internet |
| * Protocol stack which, as of this implementation, may be either |
| * BSD/POSIX Sockets, LwIP or Network.framework. |
| * |
| * Major abstractions provided are: |
| * |
| * * Timers |
| * * Domain Name System (DNS) resolution |
| * * TCP network transport |
| * * UDP network transport |
| * * Raw network transport |
| * |
| * For BSD/POSIX Sockets, event readiness notification is handled |
| * via file descriptors and a traditional poll / select |
| * implementation on the platform adaptation. |
| * |
| * For LwIP, event readiness notification is handled via events / |
| * messages and platform- and system-specific hooks for the event |
| * / message system. |
| * |
| */ |
| |
| #pragma once |
| |
| #ifndef __STDC_LIMIT_MACROS |
| #define __STDC_LIMIT_MACROS |
| #endif |
| |
| #include <inet/InetConfig.h> |
| |
| #include <inet/IANAConstants.h> |
| #include <inet/IPAddress.h> |
| #include <inet/IPPrefix.h> |
| #include <inet/InetError.h> |
| #include <inet/InetInterface.h> |
| #include <inet/InetLayerBasis.h> |
| #include <inet/InetLayerEvents.h> |
| |
| #if INET_CONFIG_ENABLE_DNS_RESOLVER |
| #include <inet/DNSResolver.h> |
| #endif // INET_CONFIG_ENABLE_DNS_RESOLVER |
| |
| #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
| #include <inet/RawEndPoint.h> |
| #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
| |
| #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
| #include <inet/TCPEndPoint.h> |
| #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
| |
| #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
| #include <inet/UDPEndPoint.h> |
| #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
| |
| #if CHIP_SYSTEM_CONFIG_USE_SOCKETS |
| #if INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
| #include <inet/AsyncDNSResolverSockets.h> |
| #endif // INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
| #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS |
| |
| #include <system/SystemLayer.h> |
| #include <system/SystemStats.h> |
| |
| #include <support/DLLUtil.h> |
| |
| #if INET_CONFIG_MAX_DROPPABLE_EVENTS |
| |
| #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING |
| #include <pthread.h> |
| #include <semaphore.h> |
| #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING |
| |
| #if CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING |
| #include <FreeRTOS.h> |
| #include <semphr.h> |
| #endif // CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING |
| |
| #endif // INET_CONFIG_MAX_DROPPABLE_EVENTS |
| |
| #include <stdint.h> |
| |
| namespace chip { |
| namespace Inet { |
| |
| // Forward Declarations |
| |
| class InetLayer; |
| |
| namespace Platform { |
| namespace InetLayer { |
| |
| extern INET_ERROR WillInit(Inet::InetLayer * aLayer, void * aContext); |
| extern void DidInit(Inet::InetLayer * aLayer, void * aContext, INET_ERROR anError); |
| |
| extern INET_ERROR WillShutdown(Inet::InetLayer * aLayer, void * aContext); |
| extern void DidShutdown(Inet::InetLayer * aLayer, void * aContext, INET_ERROR anError); |
| |
| } // namespace InetLayer |
| } // namespace Platform |
| |
| /** |
| * @class InetLayer |
| * |
| * @brief |
| * This provides access to Internet services, including timers, |
| * Domain Name System (DNS) resolution, TCP network transport, UDP |
| * network transport, and raw network transport, for a single |
| * thread. |
| * |
| * For BSD/POSIX Sockets, event readiness notification is handled |
| * via file descriptors and a traditional poll / select |
| * implementation on the platform adaptation. |
| * |
| * For LwIP, event readiness notification is handle via events / |
| * messages and platform- and system-specific hooks for the event / |
| * message system. |
| * |
| */ |
| class DLL_EXPORT InetLayer |
| { |
| #if INET_CONFIG_ENABLE_DNS_RESOLVER |
| friend class DNSResolver; |
| #endif // INET_CONFIG_ENABLE_DNS_RESOLVER |
| |
| #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
| friend class RawEndPoint; |
| #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
| |
| #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
| friend class TCPEndPoint; |
| #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
| |
| #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
| friend class UDPEndPoint; |
| #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
| |
| #if CHIP_SYSTEM_CONFIG_USE_SOCKETS |
| #if INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
| friend class AsyncDNSResolverSockets; |
| #endif // INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
| #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS |
| |
| public: |
| /** |
| * The current state of the InetLayer object. |
| * |
| */ |
| volatile enum { |
| kState_NotInitialized = 0, /**< Not initialized state. */ |
| kState_Initialized = 1, /**< Initialized state. */ |
| kState_ShutdownInProgress = 2, /**< State where Shutdown has been triggered. */ |
| } State; /**< [READ-ONLY] Current state. */ |
| |
| InetLayer(); |
| |
| INET_ERROR Init(chip::System::Layer & aSystemLayer, void * aContext); |
| INET_ERROR Shutdown(); |
| |
| chip::System::Layer * SystemLayer() const; |
| |
| // End Points |
| |
| #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
| INET_ERROR NewRawEndPoint(IPVersion ipVer, IPProtocol ipProto, RawEndPoint ** retEndPoint); |
| #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
| |
| #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
| INET_ERROR NewTCPEndPoint(TCPEndPoint ** retEndPoint); |
| #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
| |
| #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
| INET_ERROR NewUDPEndPoint(UDPEndPoint ** retEndPoint); |
| #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
| |
| // DNS Resolution |
| |
| #if INET_CONFIG_ENABLE_DNS_RESOLVER |
| |
| typedef DNSResolver::OnResolveCompleteFunct DNSResolveCompleteFunct; |
| |
| INET_ERROR ResolveHostAddress(const char * hostName, uint16_t hostNameLen, uint8_t options, uint8_t maxAddrs, |
| IPAddress * addrArray, DNSResolveCompleteFunct onComplete, void * appState); |
| INET_ERROR ResolveHostAddress(const char * hostName, uint16_t hostNameLen, uint8_t maxAddrs, IPAddress * addrArray, |
| DNSResolveCompleteFunct onComplete, void * appState); |
| INET_ERROR ResolveHostAddress(const char * hostName, uint8_t maxAddrs, IPAddress * addrArray, |
| DNSResolveCompleteFunct onComplete, void * appState); |
| void CancelResolveHostAddress(DNSResolveCompleteFunct onComplete, void * appState); |
| |
| #endif // INET_CONFIG_ENABLE_DNS_RESOLVER |
| |
| INET_ERROR GetInterfaceFromAddr(const IPAddress & addr, InterfaceId & intfId); |
| |
| INET_ERROR GetLinkLocalAddr(InterfaceId link, IPAddress * llAddr); |
| bool MatchLocalIPv6Subnet(const IPAddress & addr); |
| |
| #if CHIP_SYSTEM_CONFIG_USE_SOCKETS |
| void PrepareSelect(int & nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval & sleepTime); |
| void HandleSelectResult(int selectRes, fd_set * readfds, fd_set * writefds, fd_set * exceptfds); |
| #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS |
| |
| static void UpdateSnapshot(chip::System::Stats::Snapshot & aSnapshot); |
| |
| void * GetPlatformData(); |
| void SetPlatformData(void * aPlatformData); |
| |
| #if CHIP_SYSTEM_CONFIG_USE_LWIP |
| static chip::System::Error HandleInetLayerEvent(chip::System::Object & aTarget, chip::System::EventType aEventType, |
| uintptr_t aArgument); |
| |
| static chip::System::LwIPEventHandlerDelegate sInetEventHandlerDelegate; |
| |
| // In some implementations, there may be a shared event / message |
| // queue for the InetLayer used by other system events / messages. |
| // |
| // If the length of that queue is considerably longer than the |
| // number of packet buffers available, it may lead to buffer |
| // exhaustion. As a result, using the queue itself to implement |
| // backpressure is insufficient, and we need an external mechanism |
| // to prevent buffer starvation in the rest of the system and |
| // getting into deadlock situations. |
| |
| // For both UDP and raw network transport traffic we can easily |
| // drop incoming packets without impacting the correctness of |
| // higher level protocols. |
| |
| #if INET_CONFIG_MAX_DROPPABLE_EVENTS |
| inline static bool IsDroppableEvent(chip::System::EventType type) |
| { |
| return |
| #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
| type == kInetEvent_UDPDataReceived || |
| #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
| #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
| type == kInetEvent_RawDataReceived || |
| #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
| false; |
| } |
| |
| INET_ERROR InitQueueLimiter(void); |
| bool CanEnqueueDroppableEvent(void); |
| void DroppableEventDequeued(void); |
| |
| #if CHIP_SYSTEM_CONFIG_NO_LOCKING |
| volatile int32_t mDroppableEvents; |
| #elif CHIP_SYSTEM_CONFIG_POSIX_LOCKING |
| sem_t mDroppableEvents; |
| #elif CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING |
| #if (configSUPPORT_STATIC_ALLOCATION == 1) |
| StaticSemaphore_t mDroppableEventsObj; |
| #endif // (configSUPPORT_STATIC_ALLOCATION == 1) |
| SemaphoreHandle_t mDroppableEvents; |
| #endif // CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING |
| |
| #else // !INET_CONFIG_MAX_DROPPABLE_EVENTS |
| |
| inline static bool IsDroppableEvent(chip::System::EventType aType) { return false; } |
| |
| inline INET_ERROR InitQueueLimiter(void) { return INET_NO_ERROR; } |
| inline bool CanEnqueueDroppableEvent(void) { return true; } |
| inline void DroppableEventDequeued(void) { return; } |
| #endif // !INET_CONFIG_MAX_DROPPABLE_EVENTS |
| #endif // CHIP_SYSTEM_CONFIG_USE_LWIP |
| |
| #if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 |
| static void HandleTCPInactivityTimer(chip::System::Layer * aSystemLayer, void * aAppState, chip::System::Error aError); |
| #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 |
| |
| private: |
| void * mContext; |
| void * mPlatformData; |
| chip::System::Layer * mSystemLayer; |
| |
| #if CHIP_SYSTEM_CONFIG_USE_SOCKETS |
| #if INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
| AsyncDNSResolverSockets mAsyncDNSResolver; |
| #endif // INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
| |
| #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS |
| |
| friend INET_ERROR Platform::InetLayer::WillInit(Inet::InetLayer * aLayer, void * aContext); |
| friend void Platform::InetLayer::DidInit(Inet::InetLayer * aLayer, void * aContext, INET_ERROR anError); |
| |
| friend INET_ERROR Platform::InetLayer::WillShutdown(Inet::InetLayer * aLayer, void * aContext); |
| friend void Platform::InetLayer::DidShutdown(Inet::InetLayer * aLayer, void * aContext, INET_ERROR anError); |
| |
| bool IsIdleTimerRunning(); |
| }; |
| |
| inline chip::System::Layer * InetLayer::SystemLayer() const |
| { |
| return mSystemLayer; |
| } |
| |
| /** |
| * @class IPPacketInfo |
| * |
| * @brief |
| * Information about an incoming/outgoing message/connection. |
| * |
| * @warning |
| * Do not alter the contents of this class without first reading and understanding |
| * the code/comments in IPEndPointBasis::GetPacketInfo(). |
| */ |
| class IPPacketInfo |
| { |
| public: |
| IPAddress SrcAddress; /**< The source IPAddress in the packet. */ |
| IPAddress DestAddress; /**< The destination IPAddress in the packet. */ |
| InterfaceId Interface; /**< The interface identifier for the connection. */ |
| uint16_t SrcPort; /**< The source port in the packet. */ |
| uint16_t DestPort; /**< The destination port in the packet. */ |
| |
| void Clear(); |
| }; |
| |
| extern INET_ERROR ParseHostAndPort(const char * aString, uint16_t aStringLen, const char *& aHost, uint16_t & aHostLen, |
| uint16_t & aPort); |
| |
| extern INET_ERROR ParseHostPortAndInterface(const char * aString, uint16_t aStringLen, const char *& aHost, uint16_t & aHostLen, |
| uint16_t & aPort, const char *& aInterface, uint16_t & aInterfaceLen); |
| |
| } // namespace Inet |
| } // namespace chip |