diff --git a/src/Makefile b/src/Makefile index 9cc0a05bd4dc7f..d822552004f3ab 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ TOPTARGETS := all clean run_tests -SUBDIRS = lwip system lib/core lib/support inet +SUBDIRS = lwip system lib/core lib/support $(TOPTARGETS): $(SUBDIRS) $(SUBDIRS): diff --git a/src/inet/AsyncDNSResolverSockets.cpp b/src/inet/AsyncDNSResolverSockets.cpp deleted file mode 100644 index 5f6d596e32ee46..00000000000000 --- a/src/inet/AsyncDNSResolverSockets.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* - * - * - * - * 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 implements AsyncDNSResolverSockets, the object that implements - * Asynchronous Domain Name System (DNS) resolution in InetLayer. - * - */ -#include -#include -#include -#include -#include -#include - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#if INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - -#include "AsyncDNSResolverSockets.h" - -namespace chip { -namespace Inet { - -/** - * The explicit initializer for the AsynchronousDNSResolverSockets class. - * This initializes the mutex and semaphore variables and creates the - * threads for handling the asynchronous DNS resolution. - * - * @param[in] aInet A pointer to the InetLayer object. - * - * @retval #INET_NO_ERROR if initialization is - * successful. - * @retval other appropriate POSIX network or OS error. - */ -INET_ERROR AsyncDNSResolverSockets::Init(InetLayer *aInet) -{ - INET_ERROR err = INET_NO_ERROR; - int pthreadErr; - - mInet = aInet; - - mAsyncDNSQueueHead = NULL; - mAsyncDNSQueueTail = NULL; - - pthreadErr = pthread_cond_init(&mAsyncDNSCondVar, NULL); - VerifyOrDie(pthreadErr == 0); - - pthreadErr = pthread_mutex_init(&mAsyncDNSMutex, NULL); - VerifyOrDie(pthreadErr == 0); - - // Create the thread pool for asynchronous DNS resolution. - for (int i = 0; i < INET_CONFIG_DNS_ASYNC_MAX_THREAD_COUNT; i++) - { - pthreadErr = pthread_create(&mAsyncDNSThreadHandle[i], NULL, &AsyncDNSThreadRun, this); - VerifyOrDie(pthreadErr == 0); - } - - return err; -} - -/** - * This is the explicit deinitializer of the AsyncDNSResolverSockets class - * and it takes care of shutting the threads down and destroying the mutex - * and semaphore variables. - * - * @retval #INET_NO_ERROR if shutdown is successful. - * @retval other appropriate POSIX network or OS error. - */ -INET_ERROR AsyncDNSResolverSockets::Shutdown(void) -{ - INET_ERROR err = INET_NO_ERROR; - int pthreadErr; - - AsyncMutexLock(); - - mInet->State = InetLayer::kState_ShutdownInProgress; - - pthreadErr = pthread_cond_broadcast(&mAsyncDNSCondVar); - VerifyOrDie(pthreadErr == 0); - - AsyncMutexUnlock(); - - // Have the chip thread join the thread pool for asynchronous DNS resolution. - for (int i = 0; i < INET_CONFIG_DNS_ASYNC_MAX_THREAD_COUNT; i++) - { - pthreadErr = pthread_join(mAsyncDNSThreadHandle[i], NULL); - VerifyOrDie(pthreadErr == 0); - } - - pthreadErr = pthread_mutex_destroy(&mAsyncDNSMutex); - VerifyOrDie(pthreadErr == 0); - - pthreadErr = pthread_cond_destroy(&mAsyncDNSCondVar); - VerifyOrDie(pthreadErr == 0); - - return err; -} - -/** - * This method prepares a DNSResolver object prior to asynchronous resolution. - * - * @param[in] resolver A reference to an allocated DNSResolver object. - * - * @param[in] hostName A pointer to a C string representing the host name - * to be queried. - * @param[in] hostNameLen The string length of host name. - * @param[in] options An integer value controlling how host name address - * resolution is performed. Values are from the #DNSOptions - * enumeration. - * @param[in] maxAddrs The maximum number of addresses to store in the DNS - * table. - * @param[in] addrArray A pointer to the DNS table. - * @param[in] onComplete A pointer to the callback function when a DNS - * request is complete. - * @param[in] appState A pointer to the application state to be passed to - * onComplete when a DNS request is complete. - * - * @retval INET_NO_ERROR if a DNS request is handled - * successfully. - * - */ -INET_ERROR AsyncDNSResolverSockets::PrepareDNSResolver(DNSResolver &resolver, const char *hostName, uint16_t hostNameLen, - uint8_t options, uint8_t maxAddrs, IPAddress *addrArray, - DNSResolver::OnResolveCompleteFunct onComplete, void *appState) -{ - INET_ERROR err = INET_NO_ERROR; - - memcpy(resolver.asyncHostNameBuf, hostName, hostNameLen); - resolver.asyncHostNameBuf[hostNameLen] = 0; - resolver.MaxAddrs = maxAddrs; - resolver.NumAddrs = 0; - resolver.DNSOptions = options; - resolver.AddrArray = addrArray; - resolver.AppState = appState; - resolver.OnComplete = onComplete; - resolver.asyncDNSResolveResult = INET_NO_ERROR; - resolver.mState = DNSResolver::kState_Active; - resolver.pNextAsyncDNSResolver = NULL; - - return err; -} - -/** - * Enqueue a DNSResolver object for asynchronous IP address resolution of a specified hostname. - * - * @param[in] resolver A reference to the DNSResolver object. - * - * @retval #INET_NO_ERROR if a DNS request is queued - * successfully. - * @retval #INET_ERROR_NO_MEMORY if the Inet layer resolver pool - * is full. - * @retval other appropriate POSIX network or OS error. - * - */ -INET_ERROR AsyncDNSResolverSockets::EnqueueRequest(DNSResolver &resolver) -{ - INET_ERROR err = INET_NO_ERROR; - int pthreadErr; - - AsyncMutexLock(); - - // Add the DNSResolver object to the queue. - if (mAsyncDNSQueueHead == NULL) - { - mAsyncDNSQueueHead = &resolver; - } - - if (mAsyncDNSQueueTail != NULL) - { - mAsyncDNSQueueTail->pNextAsyncDNSResolver = &resolver; - } - - mAsyncDNSQueueTail = &resolver; - - pthreadErr = pthread_cond_signal(&mAsyncDNSCondVar); - VerifyOrDie(pthreadErr == 0); - - AsyncMutexUnlock(); - - return err; -} - -/** - * Dequeue a DNSResolver object from the queue if there is one. - * Make the worker thread block if there is no item in the queue. - * - */ -INET_ERROR AsyncDNSResolverSockets::DequeueRequest(DNSResolver **outResolver) -{ - INET_ERROR err = INET_NO_ERROR; - int pthreadErr; - - AsyncMutexLock(); - - // block until there is work to do or we detect a shutdown - while ( (mAsyncDNSQueueHead == NULL) && - (mInet->State == InetLayer::kState_Initialized) ) - { - pthreadErr = pthread_cond_wait(&mAsyncDNSCondVar, &mAsyncDNSMutex); - VerifyOrDie(pthreadErr == 0); - } - - chipLogDetail(Inet, "Async DNS worker thread woke up."); - - // on shutdown, return NULL. Otherwise, pop the head of the DNS request queue - if (mInet->State != InetLayer::kState_Initialized) - { - *outResolver = NULL; - } - else - { - *outResolver = const_cast(mAsyncDNSQueueHead); - - mAsyncDNSQueueHead = mAsyncDNSQueueHead->pNextAsyncDNSResolver; - - if (mAsyncDNSQueueHead == NULL) - { - // Queue is empty - mAsyncDNSQueueTail = NULL; - } - } - - AsyncMutexUnlock(); - - return err; -} - -/** - * Cancel an outstanding DNS query that may still be active. - * - * @param[in] resolver A reference to the DNSResolver object. - */ -INET_ERROR AsyncDNSResolverSockets::Cancel(DNSResolver &resolver) -{ - INET_ERROR err = INET_NO_ERROR; - - AsyncMutexLock(); - - resolver.mState = DNSResolver::kState_Canceled; - - AsyncMutexUnlock(); - - return err; -} - -void AsyncDNSResolverSockets::UpdateDNSResult(DNSResolver &resolver, struct addrinfo *inLookupRes) -{ - resolver.NumAddrs = 0; - - for (struct addrinfo *addr = inLookupRes; addr != NULL && resolver.NumAddrs < resolver.MaxAddrs; addr = addr->ai_next, resolver.NumAddrs++) - { - resolver.AddrArray[resolver.NumAddrs] = IPAddress::FromSockAddr(*addr->ai_addr); - } -} - -void AsyncDNSResolverSockets::Resolve(DNSResolver &resolver) -{ - struct addrinfo gaiHints; - struct addrinfo * gaiResults = NULL; - int gaiReturnCode; - - // Configure the hints argument for getaddrinfo() - resolver.InitAddrInfoHints(gaiHints); - - // Call getaddrinfo() to perform the name resolution. - gaiReturnCode = getaddrinfo(resolver.asyncHostNameBuf, NULL, &gaiHints, &gaiResults); - - // Mutex protects the read and write operation on resolver->mState - AsyncMutexLock(); - - // Process the return code and results list returned by getaddrinfo(). If the call - // was successful this will copy the resultant addresses into the caller's array. - resolver.asyncDNSResolveResult = resolver.ProcessGetAddrInfoResult(gaiReturnCode, gaiResults); - - // Set the DNS resolver state. - resolver.mState = DNSResolver::kState_Complete; - - // Release lock. - AsyncMutexUnlock(); - - return; -} - -/* Event handler function for asynchronous DNS notification */ -void AsyncDNSResolverSockets::DNSResultEventHandler (chip::System::Layer* aLayer, void* aAppState, chip::System::Error aError) -{ - DNSResolver *resolver = static_cast(aAppState); - - if (resolver) - { - resolver->HandleAsyncResolveComplete(); - } -} - -void AsyncDNSResolverSockets::NotifyChipThread(DNSResolver *resolver) -{ - // Post work item via Timer Event for the chip thread - chip::System::Layer& lSystemLayer = resolver->SystemLayer(); - - chipLogDetail(Inet, "Posting DNS completion event to chip thread."); - lSystemLayer.ScheduleWork(AsyncDNSResolverSockets::DNSResultEventHandler, resolver); -} - -void *AsyncDNSResolverSockets::AsyncDNSThreadRun(void *args) -{ - - INET_ERROR err = INET_NO_ERROR; - AsyncDNSResolverSockets *asyncResolver = static_cast(args); - - while (true) - { - DNSResolver *request = NULL; - - // Dequeue a DNSResolver for resolution. This function would block until there - // is an item in the queue or shutdown has been called. - err = asyncResolver->DequeueRequest(&request); - - // If shutdown has been called, DeQueue would return with an empty request. - // In that case, break out of the loop and exit thread. - VerifyOrExit(err == INET_NO_ERROR && request != NULL, ); - - if (request->mState != DNSResolver::kState_Canceled) - { - asyncResolver->Resolve(*request); - } - - asyncResolver->NotifyChipThread(request); - } - -exit: - chipLogDetail(Inet, "Async DNS worker thread exiting."); - return NULL; -} - -void AsyncDNSResolverSockets::AsyncMutexLock(void) -{ - int pthreadErr; - - pthreadErr = pthread_mutex_lock(&mAsyncDNSMutex); - VerifyOrDie(pthreadErr == 0); -} - -void AsyncDNSResolverSockets::AsyncMutexUnlock(void) -{ - int pthreadErr; - - pthreadErr = pthread_mutex_unlock(&mAsyncDNSMutex); - VerifyOrDie(pthreadErr == 0); -} - -} // namespace Inet -} // namespace chip -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS diff --git a/src/inet/AsyncDNSResolverSockets.h b/src/inet/AsyncDNSResolverSockets.h deleted file mode 100644 index 7da65796054e18..00000000000000 --- a/src/inet/AsyncDNSResolverSockets.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * - * - * 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 the AsyncDNSResolver, the object that performs - * Asynchronous Domain Name System (DNS) resolution in InetLayer. - * - */ -#ifndef _ASYNC_DNS_SOCKETS_H_ -#define _ASYNC_DNS_SOCKETS_H_ - -#include -#include - -#if INET_CONFIG_ENABLE_DNS_RESOLVER -#include -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#if INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#include -#include -#include - -namespace chip { -namespace Inet { - -/** - * @class AsyncDNSResolverSockets - * - * @brief - * This is an internal class to InetLayer that provides helper APIs for - * Asynchronous Domain Name System (DNS) resolution in InetLayer. - * There is no public interface available for the application layer. - * - */ -class AsyncDNSResolverSockets -{ - friend class InetLayer; - friend class DNSResolver; -public: - - INET_ERROR EnqueueRequest(DNSResolver &resolver); - - INET_ERROR Init(InetLayer *inet); - - INET_ERROR Cancel(DNSResolver &resolver); - - INET_ERROR Shutdown(void); - - INET_ERROR PrepareDNSResolver(DNSResolver &resolver, const char *hostName, uint16_t hostNameLen, - uint8_t options, uint8_t maxAddrs, IPAddress *addrArray, - DNSResolver::OnResolveCompleteFunct onComplete, void *appState); - -private: - pthread_t mAsyncDNSThreadHandle[INET_CONFIG_DNS_ASYNC_MAX_THREAD_COUNT]; - pthread_mutex_t mAsyncDNSMutex; /* Mutex for accessing the DNSResolver queue. */ - pthread_cond_t mAsyncDNSCondVar; /* Condition Variable for thread synchronization. */ - volatile DNSResolver *mAsyncDNSQueueHead; /* The head of the asynchronous DNSResolver object queue. */ - volatile DNSResolver *mAsyncDNSQueueTail; /* The tail of the asynchronous DNSResolver object queue. */ - InetLayer *mInet; /* The pointer to the InetLayer. */ - static void DNSResultEventHandler(chip::System::Layer* aLayer, void* aAppState, chip::System::Error aError); /* Timer event handler function for asynchronous DNS notification */ - - INET_ERROR DequeueRequest(DNSResolver **outResolver); - - bool ShouldThreadShutdown(void); - - void Resolve(DNSResolver &resolver); - - void UpdateDNSResult(DNSResolver &resolver, struct addrinfo *lookupRes); - - static void *AsyncDNSThreadRun(void *args); - - static void NotifyChipThread(DNSResolver *resolver); - - void AsyncMutexLock(void); - - void AsyncMutexUnlock(void); -}; - -} // namespace Inet -} // namespace chip -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#endif // !defined(_ASYNC_DNS_SOCKETS_H_) diff --git a/src/inet/DNSResolver.cpp b/src/inet/DNSResolver.cpp deleted file mode 100644 index 7a83defd7a8855..00000000000000 --- a/src/inet/DNSResolver.cpp +++ /dev/null @@ -1,544 +0,0 @@ -/* - * - * - * - * 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 implements DNSResolver, the object that abstracts - * Domain Name System (DNS) resolution in InetLayer. - * - */ - -#include -#include -#include - -#include - -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#include - -#if LWIP_VERSION_MAJOR < 2 -#define LWIP_DNS_FOUND_CALLBACK_TYPE dns_found_callback -#endif // LWIP_VERSION_MAJOR < 2 -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -namespace chip { -namespace Inet { - -chip::System::ObjectPool DNSResolver::sPool; - -/** - * This method revolves a host name into a list of IP addresses. - * - * @note - * Even if the operation completes successfully, - * the result might be a zero-length list of IP addresses. - * Most of the error generated are returned via the - * application callback. - * - * @param[in] hostName A pointer to a C string representing the host name - * to be queried. - * @param[in] hostNameLen The string length of host name. - * @param[in] maxAddrs The maximum number of addresses to store in the DNS - * table. - * @param[in] options An integer value controlling how host name address - * resolution is performed. Values are from the #DNSOptions - * enumeration. - * @param[in] addrArray A pointer to the DNS table. - * @param[in] onComplete A pointer to the callback function when a DNS - * request is complete. - * @param[in] appState A pointer to the application state to be passed to - * onComplete when a DNS request is complete. - * - * @retval INET_NO_ERROR if a DNS request is handled - * successfully. - * - * @retval INET_ERROR_NOT_IMPLEMENTED if DNS resolution is not enabled on - * the underlying platform. - * - * @retval _other_ if other POSIX network or OS error - * was returned by the underlying DNS - * resolver implementation. - * - */ -INET_ERROR DNSResolver::Resolve(const char *hostName, uint16_t hostNameLen, uint8_t options, - uint8_t maxAddrs, IPAddress *addrArray, - DNSResolver::OnResolveCompleteFunct onComplete, void *appState) -{ - INET_ERROR res = INET_NO_ERROR; - -#if !CHIP_SYSTEM_CONFIG_USE_SOCKETS && !LWIP_DNS - Release(); - return INET_ERROR_NOT_IMPLEMENTED; -#endif // !CHIP_SYSTEM_CONFIG_USE_SOCKETS && !LWIP_DNS - - uint8_t addrFamilyOption = (options & kDNSOption_AddrFamily_Mask); - uint8_t optionFlags = (options & kDNSOption_Flags_Mask); - - // Check that the supplied options are valid. - if ((addrFamilyOption != kDNSOption_AddrFamily_Any && - addrFamilyOption != kDNSOption_AddrFamily_IPv4Only && - addrFamilyOption != kDNSOption_AddrFamily_IPv4Preferred && - addrFamilyOption != kDNSOption_AddrFamily_IPv6Only && - addrFamilyOption != kDNSOption_AddrFamily_IPv6Preferred) || - (optionFlags & ~kDNSOption_ValidFlags) != 0) - { - Release(); - return INET_ERROR_BAD_ARGS; - } - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || (CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_DNS) - - // TODO: Eliminate the need for a local buffer when running on LwIP by changing - // the LwIP DNS interface to support non-nul terminated strings. - - char hostNameBuf[NL_DNS_HOSTNAME_MAX_LEN + 1]; // DNS limits hostnames to 253 max characters. - - memcpy(hostNameBuf, hostName, hostNameLen); - hostNameBuf[hostNameLen] = 0; - - AppState = appState; - AddrArray = addrArray; - MaxAddrs = maxAddrs; - NumAddrs = 0; - DNSOptions = options; - OnComplete = onComplete; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - - u8_t lwipAddrType; - -#if INET_CONFIG_ENABLE_IPV4 - switch (addrFamilyOption) - { - case kDNSOption_AddrFamily_IPv4Only: - lwipAddrType = LWIP_DNS_ADDRTYPE_IPV4; - break; - case kDNSOption_AddrFamily_Any: - case kDNSOption_AddrFamily_IPv4Preferred: - lwipAddrType = LWIP_DNS_ADDRTYPE_IPV4_IPV6; - break; - case kDNSOption_AddrFamily_IPv6Only: - lwipAddrType = LWIP_DNS_ADDRTYPE_IPV6; - break; - case kDNSOption_AddrFamily_IPv6Preferred: - lwipAddrType = LWIP_DNS_ADDRTYPE_IPV6_IPV4; - break; - default: - chipDie(); - } -#else // INET_CONFIG_ENABLE_IPV4 - lwipAddrType = LWIP_DNS_ADDRTYPE_IPV6; -#endif // INET_CONFIG_ENABLE_IPV4 - -#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 - -#if INET_CONFIG_ENABLE_IPV4 - if (addrFamilyOption == kDNSOption_AddrFamily_IPv6Only) -#endif - { - Release(); - return INET_ERROR_NOT_IMPLEMENTED; - } - -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - ip_addr_t lwipAddr; - LWIP_DNS_FOUND_CALLBACK_TYPE lwipCallback = reinterpret_cast(LwIPHandleResolveComplete); - - err_t lwipErr = -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - dns_gethostbyname_addrtype(hostNameBuf, &lwipAddr, lwipCallback, this, lwipAddrType); -#else - dns_gethostbyname(hostNameBuf, &lwipAddr, lwipCallback, this); -#endif - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - if (lwipErr == ERR_OK) - { - chip::System::Layer& lSystemLayer = SystemLayer(); - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - AddrArray[0] = IPAddress::FromLwIPAddr(lwipAddr); -#else - AddrArray[0] = IPAddress::FromIPv4(lwipAddr); -#endif - NumAddrs = 1; - - lSystemLayer.PostEvent(*this, kInetEvent_DNSResolveComplete, 0); - } - else if (lwipErr != ERR_INPROGRESS) - { - res = chip::System::MapErrorLwIP(lwipErr); - Release(); - } - - return res; - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - struct addrinfo gaiHints; - struct addrinfo * gaiResults = NULL; - int gaiReturnCode; - - // Configure the hints argument for getaddrinfo() - InitAddrInfoHints(gaiHints); - - // Call getaddrinfo() to perform the name resolution. - gaiReturnCode = getaddrinfo(hostNameBuf, NULL, &gaiHints, &gaiResults); - - // Process the return code and results list returned by getaddrinfo(). If the call - // was successful this will copy the resultant addresses into the caller's array. - res = ProcessGetAddrInfoResult(gaiReturnCode, gaiResults); - - // Invoke the caller's completion function. - onComplete(appState, res, NumAddrs, addrArray); - - // Release DNSResolver object. - Release(); - - return INET_NO_ERROR; - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || (CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_DNS) -} - - -/** - * This method cancels DNS requests that are in progress. - * - * @retval INET_NO_ERROR. - * - */ -INET_ERROR DNSResolver::Cancel() -{ -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // NOTE: LwIP does not support canceling DNS requests that are in progress. As a consequence, - // we can't release the DNSResolver object until LwIP calls us back (because LwIP retains a - // pointer to the DNSResolver object while the request is active). However, now that the - // application has called Cancel() we have to make sure to NOT call their OnComplete function - // when the request completes. - // - // To ensure the right thing happens, we NULL the OnComplete pointer here, which signals the - // code in HandleResolveComplete() and LwIPHandleResolveComplete() to not interact with the - // application's state data (AddrArray) and to not call the application's callback. This has - // to happen with the LwIP lock held, since LwIPHandleResolveComplete() runs on LwIP's thread. - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Signal that the request has been canceled by clearing the state of the resolver object. - OnComplete = NULL; - AddrArray = NULL; - MaxAddrs = 0; - NumAddrs = 0; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#if INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - // NOTE: DNS lookups can be canceled only when using the asynchronous mode. - - InetLayer& inet = Layer(); - - OnComplete = NULL; - AppState = NULL; - inet.mAsyncDNSResolver.Cancel(*this); - -#endif // INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return INET_NO_ERROR; -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -/** - * This method is called by InetLayer on success, failure, or timeout of a - * DNS request. - * - */ -void DNSResolver::HandleResolveComplete() -{ - // Call the application's completion handler if the request hasn't been canceled. - if (OnComplete != NULL) - OnComplete(AppState, (NumAddrs > 0) ? INET_NO_ERROR : INET_ERROR_HOST_NOT_FOUND, NumAddrs, AddrArray); - - // Release the resolver object. - Release(); -} - - -/** - * This method is called by LwIP network stack on success, failure, or timeout - * of a DNS request. - * - * @param[in] name A pointer to a NULL-terminated C string - * representing the host name that is queried. - * @param[in] ipaddr A pointer to a list of resolved IP addresses. - * @param[in] callback_arg A pointer to the arguments that are passed to - * the callback function. - * - */ -#if LWIP_VERSION_MAJOR > 1 -void DNSResolver::LwIPHandleResolveComplete(const char *name, const ip_addr_t *ipaddr, void *callback_arg) -#else // LWIP_VERSION_MAJOR <= 1 -void DNSResolver::LwIPHandleResolveComplete(const char *name, ip_addr_t *ipaddr, void *callback_arg) -#endif // LWIP_VERSION_MAJOR <= 1 -{ - DNSResolver *resolver = (DNSResolver *)callback_arg; - - if (resolver != NULL) - { - chip::System::Layer& lSystemLayer = resolver->SystemLayer(); - - // Copy the resolved address to the application supplied buffer, but only if the request hasn't been canceled. - if (resolver->OnComplete != NULL && ipaddr != NULL) - { -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - resolver->AddrArray[0] = IPAddress::FromLwIPAddr(*ipaddr); -#else - resolver->AddrArray[0] = IPAddress::FromIPv4(*ipaddr); -#endif - resolver->NumAddrs = 1; - } - - lSystemLayer.PostEvent(*resolver, kInetEvent_DNSResolveComplete, 0); - } -} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -void DNSResolver::InitAddrInfoHints(struct addrinfo & hints) -{ - uint8_t addrFamilyOption = (DNSOptions & kDNSOption_AddrFamily_Mask); - - memset(&hints, 0, sizeof(hints)); -#if INET_CONFIG_ENABLE_IPV4 - if (addrFamilyOption == kDNSOption_AddrFamily_IPv4Only) - { - hints.ai_family = AF_INET; - } - else if (addrFamilyOption == kDNSOption_AddrFamily_IPv6Only) - { - hints.ai_family = AF_INET6; - } - else - { - hints.ai_family = AF_UNSPEC; - } -#else // INET_CONFIG_ENABLE_IPV4 - hints.ai_family = AF_INET6; -#endif // INET_CONFIG_ENABLE_IPV4 - hints.ai_flags = AI_ADDRCONFIG; -} - -INET_ERROR DNSResolver::ProcessGetAddrInfoResult(int returnCode, struct addrinfo * results) -{ - INET_ERROR err = INET_NO_ERROR; - - // If getaddrinfo() succeeded, copy addresses in the returned addrinfo structures into the - // application's output array... - if (returnCode == 0) - { - NumAddrs = 0; - -#if INET_CONFIG_ENABLE_IPV4 - - // Based on the address family option specified by the application, determine which - // types of addresses should be returned and the order in which they should appear. - uint8_t addrFamilyOption = (DNSOptions & kDNSOption_AddrFamily_Mask); - int primaryFamily, secondaryFamily; - switch (addrFamilyOption) - { - case kDNSOption_AddrFamily_Any: - primaryFamily = AF_UNSPEC; - secondaryFamily = AF_UNSPEC; - break; - case kDNSOption_AddrFamily_IPv4Only: - primaryFamily = AF_INET; - secondaryFamily = AF_UNSPEC; - break; - case kDNSOption_AddrFamily_IPv4Preferred: - primaryFamily = AF_INET; - secondaryFamily = AF_INET6; - break; - case kDNSOption_AddrFamily_IPv6Only: - primaryFamily = AF_INET6; - secondaryFamily = AF_UNSPEC; - break; - case kDNSOption_AddrFamily_IPv6Preferred: - primaryFamily = AF_INET6; - secondaryFamily = AF_INET; - break; - default: - chipDie(); - } - - // Determine the number of addresses of each family present in the results. - // In the case of the secondary address family, only count these if they are - // to be returned in the results. - uint8_t numPrimaryAddrs = CountAddresses(primaryFamily, results); - uint8_t numSecondaryAddrs = (secondaryFamily != AF_UNSPEC) ? CountAddresses(secondaryFamily, results) : 0; - uint8_t numAddrs = numPrimaryAddrs + numSecondaryAddrs; - - // If the total number of addresses to be returned exceeds the application - // specified max, ensure that at least 1 address from the secondary family - // appears in the result (unless of course there are no such addresses or - // the max is set to 1). - // This ensures the application will try at least one secondary address - // when attempting to communicate with the host. - if (numAddrs > MaxAddrs && MaxAddrs > 1 && numPrimaryAddrs > 0 && numSecondaryAddrs > 0) - { - numPrimaryAddrs = ::chip::min(numPrimaryAddrs, (uint8_t)(MaxAddrs - 1)); - } - - // Copy the primary addresses into the beginning of the application's output array, - // up to the limit determined above. - CopyAddresses(primaryFamily, numPrimaryAddrs, results); - - // If secondary addresses are being returned, copy them into the output array after - // the primary addresses. - if (numSecondaryAddrs != 0) - { - CopyAddresses(secondaryFamily, numSecondaryAddrs, results); - } - -#else // INET_CONFIG_ENABLE_IPV4 - - // Copy IPv6 addresses into the application's output array. - CopyAddresses(AF_INET6, UINT8_MAX, results); - -#endif // INET_CONFIG_ENABLE_IPV4 - - // If in the end no addresses were returned, treat this as a "host not found" error. - if (NumAddrs == 0) - { - err = INET_ERROR_HOST_NOT_FOUND; - } - } - - // Otherwise, getaddrinfo() failed, so translate the return code to an appropriate - // Inet error... - else - { - switch (returnCode) - { - case EAI_NONAME: - case EAI_NODATA: - case EAI_ADDRFAMILY: - // Each of these errors is translated to "host not found" for simplicity at the - // application layer. On most systems, the errors have the following meanings: - // EAI_NONAME is returned when there are no DNS records for the requested host name. - // EAI_NODATA is returned when there are no host records (A or AAAA) for the requested - // name, but other records do exist (e.g. MX or TXT). - // EAI_ADDRFAMILY is returned when a text-form address is given as the name, but its - // address family (IPv4 or IPv6) does not match the value specified in hints.ai_family. - err = INET_ERROR_HOST_NOT_FOUND; - break; - case EAI_AGAIN: - err = INET_ERROR_DNS_TRY_AGAIN; - break; - case EAI_SYSTEM: - err = chip::System::MapErrorPOSIX(errno); - break; - default: - err = INET_ERROR_DNS_NO_RECOVERY; - break; - } - } - - // Free the results structure. - if (results != NULL) - freeaddrinfo(results); - - return err; -} - -void DNSResolver::CopyAddresses(int family, uint8_t count, const struct addrinfo * addrs) -{ - for (const struct addrinfo *addr = addrs; - addr != NULL && NumAddrs < MaxAddrs && count > 0; - addr = addr->ai_next) - { - if (family == AF_UNSPEC || addr->ai_addr->sa_family == family) - { - AddrArray[NumAddrs++] = IPAddress::FromSockAddr(*addr->ai_addr); - count--; - } - } -} - -uint8_t DNSResolver::CountAddresses(int family, const struct addrinfo * addrs) -{ - uint8_t count = 0; - - for (const struct addrinfo *addr = addrs; - addr != NULL && count < UINT8_MAX; - addr = addr->ai_next) - { - if (family == AF_UNSPEC || addr->ai_addr->sa_family == family) - { - count++; - } - } - - return count; -} - -#if INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - -void DNSResolver::HandleAsyncResolveComplete(void) -{ - // Copy the resolved address to the application supplied buffer, but only if the request hasn't been canceled. - if (OnComplete && mState != kState_Canceled) - { - OnComplete(AppState, asyncDNSResolveResult, NumAddrs, AddrArray); - } - - Release(); -} -#endif // INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -} // namespace Inet -} // namespace chip diff --git a/src/inet/DNSResolver.h b/src/inet/DNSResolver.h deleted file mode 100644 index 58fdcaaa86b3f2..00000000000000 --- a/src/inet/DNSResolver.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * - * - * - * 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 DNSResolver, the object that abstracts - * Domain Name System (DNS) resolution in InetLayer. - * - */ - -#ifndef DNSRESOLVER_H -#define DNSRESOLVER_H - -#include -#include -#include "InetLayerBasis.h" - -#define NL_DNS_HOSTNAME_MAX_LEN (253) - -struct addrinfo; - -namespace chip { -namespace Inet { - -class InetLayer; - -/** - * Options controlling how IP address resolution is performed. - */ -enum DNSOptions -{ - kDNSOption_AddrFamily_Mask = 0x07, ///< Bits within a DNSOptions integer value representing the desired address family. - kDNSOption_Flags_Mask = 0xF8, ///< Bits within a DNSOptions integer value reserved for flags. - - // Address Family Choices - kDNSOption_AddrFamily_Any = 0x00, ///< Return IPv4 and/or IPv6 addresses in the order returned by the nameserver. -#if INET_CONFIG_ENABLE_IPV4 - kDNSOption_AddrFamily_IPv4Only = 0x01, ///< Return only IPv4 addresses. - kDNSOption_AddrFamily_IPv4Preferred = 0x02, ///< Return IPv4 and/or IPv6 addresses, with IPv4 addresses listed first. -#endif - kDNSOption_AddrFamily_IPv6Only = 0x03, ///< Return only IPv6 addresses. - kDNSOption_AddrFamily_IPv6Preferred = 0x04, ///< Return IPv4 and/or IPv6 addresses, with IPv6 addresses listed first. - - // NOTE: At present there are no DNSOption flags define. - kDNSOption_ValidFlags = 0, ///< Set of all valid DNSOption flags. - - kDNSOption_Default = kDNSOption_AddrFamily_Any -}; - - -/** - * @class DNSResolver - * - * @brief - * This is an internal class to InetLayer that provides the abstraction of - * Domain Name System (DNS) resolution in InetLayer. There is no public - * interface available for the application layer. - * - */ -class DNSResolver: public InetLayerBasis -{ -private: - friend class InetLayer; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#if INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - friend class AsyncDNSResolverSockets; - - /// States of the DNSResolver object with respect to hostname resolution. - typedef enum DNSResolverState - { - kState_Unused = 0, /// sPool; - - /** - * A pointer to the callback function when a DNS request is complete. - */ - OnResolveCompleteFunct OnComplete; - - /** - * A pointer to the DNS table that stores a list of resolved addresses. - */ - IPAddress *AddrArray; - - /** - * The maximum number of addresses that could be stored in the DNS table. - */ - uint8_t MaxAddrs; - - /** - * The actual number of addresses that are stored in the DNS table. - */ - uint8_t NumAddrs; - - /** - * DNS options for the current request. - */ - uint8_t DNSOptions; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - void InitAddrInfoHints(struct addrinfo & hints); - INET_ERROR ProcessGetAddrInfoResult(int returnCode, struct addrinfo * results); - void CopyAddresses(int family, uint8_t maxAddrs, const struct addrinfo * addrs); - uint8_t CountAddresses(int family, const struct addrinfo * addrs); - -#if INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - - /* Hostname that requires resolution */ - char asyncHostNameBuf[NL_DNS_HOSTNAME_MAX_LEN + 1]; // DNS limits hostnames to 253 max characters. - - INET_ERROR asyncDNSResolveResult; - /* The next DNSResolver object in the asynchronous DNS resolution queue. */ - DNSResolver *pNextAsyncDNSResolver; - - DNSResolverState mState; - - void HandleAsyncResolveComplete(void); - -#endif // INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - INET_ERROR Resolve(const char *hostName, uint16_t hostNameLen, uint8_t options, - uint8_t maxAddrs, IPAddress *addrArray, - OnResolveCompleteFunct onComplete, void *appState); - INET_ERROR Cancel(void); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - void HandleResolveComplete(void); -#if LWIP_VERSION_MAJOR > 1 - static void LwIPHandleResolveComplete(const char *name, const ip_addr_t *ipaddr, void *callback_arg); -#else // LWIP_VERSION_MAJOR <= 1 - static void LwIPHandleResolveComplete(const char *name, ip_addr_t *ipaddr, void *callback_arg); -#endif // LWIP_VERSION_MAJOR <= 1 -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -}; - -} // namespace Inet -} // namespace chip - -#endif // !defined(DNSRESOLVER_H_) diff --git a/src/inet/EndPointBasis.cpp b/src/inet/EndPointBasis.cpp deleted file mode 100644 index 95c8634a6a4fac..00000000000000 --- a/src/inet/EndPointBasis.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * - * - * 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 contains the external implementations of methods in - * the basis class for all the various transport endpoint classes - * in the Inet layer, i.e. TCP, UDP, Raw and Tun. - */ - -#include - -#include - -namespace chip { -namespace Inet { - -void EndPointBasis::InitEndPointBasis(InetLayer& aInetLayer, void* aAppState) -{ - InitInetLayerBasis(aInetLayer, aAppState); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - mLwIPEndPointType = kLwIPEndPointType_Unknown; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - mSocket = INET_INVALID_SOCKET_FD; - mPendingIO.Clear(); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -} - -} // namespace Inet -} // namespace chip diff --git a/src/inet/EndPointBasis.h b/src/inet/EndPointBasis.h deleted file mode 100644 index ba3fca4a4ffad1..00000000000000 --- a/src/inet/EndPointBasis.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * - * - * - * 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 contains the basis class for all the various transport - * endpoint classes in the Inet layer, i.e. TCP, UDP, Raw and Tun. - */ - -#ifndef ENDPOINTBASIS_H -#define ENDPOINTBASIS_H - -#include -#include -#include "IANAConstants.h" -#include "InetLayerBasis.h" -#include -#include - -#include - -//--- Declaration of LWIP protocol control buffer structure names -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if INET_CONFIG_ENABLE_RAW_ENDPOINT -struct raw_pcb; -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT -#if INET_CONFIG_ENABLE_UDP_ENDPOINT -struct udp_pcb; -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT -#if INET_CONFIG_ENABLE_TCP_ENDPOINT -struct tcp_pcb; -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT -#if INET_CONFIG_ENABLE_TUN_ENDPOINT -struct netif; -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -namespace chip { -namespace Inet { - -/** - * @class EndPointBasis - * - * @brief Basis of internet transport endpoint classes - */ -class DLL_EXPORT EndPointBasis : public InetLayerBasis -{ -public: - /** Common state codes */ - enum { - kBasisState_Closed = 0 /**< Encapsulated descriptor is not valid. */ - }; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - /** Test whether endpoint is a POSIX socket */ - bool IsSocketsEndPoint(void) const; -#endif - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - /** Test whether endpoint is a LwIP protocol control buffer */ - bool IsLWIPEndPoint(void) const; -#endif - - /** Test whether endpoint has a valid descriptor. */ - bool IsOpenEndPoint(void) const; - -protected: -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - int mSocket; /**< Encapsulated socket descriptor. */ - IPAddressType mAddrType; /**< Protocol family, i.e. IPv4 or IPv6. */ - SocketEvents mPendingIO; /**< Socket event masks */ -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - /** Encapsulated LwIP protocol control block */ - union - { - const void* mVoid; /**< An untyped protocol control buffer reference */ -#if INET_CONFIG_ENABLE_RAW_ENDPOINT - raw_pcb* mRaw; /**< Raw network interface protocol control */ -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - udp_pcb* mUDP; /**< User datagram protocol (UDP) control */ -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - tcp_pcb* mTCP; /**< Transmission control protocol (TCP) control */ -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT -#if INET_CONFIG_ENABLE_TUN_ENDPOINT - netif* mNetIf; /**< Tunnel interface control */ -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT - }; - - enum - { - kLwIPEndPointType_Unknown = 0, - - kLwIPEndPointType_Raw = 1, - kLwIPEndPointType_UDP = 2, - kLwIPEndPointType_UCP = 3, - kLwIPEndPointType_TCP = 4 - }; - - uint8_t mLwIPEndPointType; - - void DeferredFree(chip::System::Object::ReleaseDeferralErrorTactic aTactic); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - - void InitEndPointBasis(InetLayer& aInetLayer, void* aAppState = NULL); -}; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -inline bool EndPointBasis::IsSocketsEndPoint(void) const -{ - return mSocket >= 0; -} -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -inline bool EndPointBasis::IsLWIPEndPoint(void) const -{ - return mVoid != NULL; -} -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -inline bool EndPointBasis::IsOpenEndPoint(void) const -{ - bool lResult = false; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - lResult = (lResult || IsLWIPEndPoint()); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lResult = (lResult || IsSocketsEndPoint()); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return lResult; -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -inline void EndPointBasis::DeferredFree(chip::System::Object::ReleaseDeferralErrorTactic aTactic) -{ - if (!CHIP_SYSTEM_CONFIG_USE_SOCKETS || IsLWIPEndPoint()) - { - DeferredRelease(aTactic); - } - else - { - Release(); - } -} -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - - -} // namespace Inet -} // namespace chip - -#endif // !defined(ENDPOINTBASIS_H) diff --git a/src/inet/IANAConstants.h b/src/inet/IANAConstants.h deleted file mode 100644 index f7036ed2d3f97d..00000000000000 --- a/src/inet/IANAConstants.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * - * - * 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 contains constants corresponding to numbers assigned - * by the Internet Assigned Number Authority (IANA) that are used - * in the abstract programming interface of the Inet layer, and - * which are defined independently here from their corresponding - * definitions in any underlying IP stacks. - */ - -#ifndef IANACONSTANTS_H -#define IANACONSTANTS_H - -namespace chip { -namespace Inet { - -/** - * @enum IPVersion - * - * The version of the IP protocol being used. - * - */ -typedef enum -{ - kIPVersion_6 = 6, /**< IPv6 */ -#if INET_CONFIG_ENABLE_IPV4 - kIPVersion_4 = 4, /**< IPv4 */ -#endif // INET_CONFIG_ENABLE_IPV4 -} IPVersion; - -/** - * @enum IPProtocol - * - * The numbers of some of the protocols in the IP family. - * - */ -typedef enum -{ - kIPProtocol_ICMPv6 = 58, /**< ICMPv6 */ -#if INET_CONFIG_ENABLE_IPV4 - kIPProtocol_ICMPv4 = 1, /**< ICMPv4 */ -#endif // INET_CONFIG_ENABLE_IPV4 -} IPProtocol; - -/** - * @brief Internet protocol multicast address scope - * - * @details - * Values of the \c IPv6MulticastScope type are used to call the - * IPAddress::MakeIPv6Multicast() method. They indicate the routable - * scope of the multicast group designated by the result. These numbers are - * registered by IETF with IANA. - */ -typedef enum -{ - /** Interface-local scope. */ - kIPv6MulticastScope_Interface = 1, - - /** Link-local scope. */ - kIPv6MulticastScope_Link = 2, - -#if INET_CONFIG_ENABLE_IPV4 - /** Realm-local ("IPv4") scope. */ - kIPv6MulticastScope_IPv4 = 3, -#else // !INET_CONFIG_ENABLE_IPV4 - /** Realm-local scope. */ - kIPv6MulticastScope_Realm = 3, -#endif // !INET_CONFIG_ENABLE_IPV4 - - /** Realm-local scope. */ - kIPv6MulticastScope_Admin = 4, - - /** Realm-local scope. */ - kIPv6MulticastScope_Site = 5, - - /** Organization-local scope. */ - kIPv6MulticastScope_Organization = 8, - - /** Global scope. */ - kIPv6MulticastScope_Global = 14 -} IPv6MulticastScope; - -/** - * @brief Internet protocol multicast group identifiers - * - * @details - * Values of the \c IPV6MulticastGroup type are used to call the - * IPAddress::MakeIPv6Multicast() method. They indicate - * distinguished group identifiers registered by IETF with IANA. - */ -enum IPV6MulticastGroup -{ - kIPV6MulticastGroup_AllNodes = 1, /** RFC 4291 */ - kIPV6MulticastGroup_AllRouters = 2 /** RFC 4291 */ -}; - -} // namespace Inet -} // namespace chip - -#endif // !defined(IANACONSTANTS_H) diff --git a/src/inet/IPAddress-StringFuncts.cpp b/src/inet/IPAddress-StringFuncts.cpp deleted file mode 100644 index c6f94508ebed1f..00000000000000 --- a/src/inet/IPAddress-StringFuncts.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * - * - * - * 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 implements the human-readable string formatting and - * parsing methods from class Inet::IPAddress. - * - */ - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif -#include -#include - -#include - -#if !CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#endif - -namespace chip { -namespace Inet { - -char *IPAddress::ToString(char *buf, uint32_t bufSize) const -{ -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if INET_CONFIG_ENABLE_IPV4 - if (IsIPv4()) - { -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - ip4_addr_t ip4_addr = ToIPv4(); - ip4addr_ntoa_r(&ip4_addr, buf, (int)bufSize); -#else // LWIP_VERSION_MAJOR <= 1 - ip_addr_t ip4_addr = ToIPv4(); - ipaddr_ntoa_r(&ip4_addr, buf, (int)bufSize); -#endif // LWIP_VERSION_MAJOR <= 1 - } - else -#endif // INET_CONFIG_ENABLE_IPV4 - { - ip6_addr_t ip6_addr = ToIPv6(); - ip6addr_ntoa_r(&ip6_addr, buf, (int)bufSize); - } -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP -#if INET_CONFIG_ENABLE_IPV4 - if (IsIPv4()) - { - buf = (char *)inet_ntop(AF_INET, (const void *) &Addr[3], buf, bufSize); - } - else -#endif // INET_CONFIG_ENABLE_IPV4 - { - buf = (char *)inet_ntop(AF_INET6, (const void *) Addr, buf, bufSize); - } -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP - - return buf; -} - -bool IPAddress::FromString(const char *str, IPAddress& output) -{ -#if INET_CONFIG_ENABLE_IPV4 - if (strchr(str, ':') == NULL) - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - ip4_addr_t ipv4Addr; - if (!ip4addr_aton(str, &ipv4Addr)) - return false; -#else // LWIP_VERSION_MAJOR <= 1 - ip_addr_t ipv4Addr; - if (!ipaddr_aton(str, &ipv4Addr)) - return false; -#endif // LWIP_VERSION_MAJOR <= 1 -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP - struct in_addr ipv4Addr; - if (inet_pton(AF_INET, str, &ipv4Addr) < 1) - return false; -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP - output = FromIPv4(ipv4Addr); - } - else -#endif // INET_CONFIG_ENABLE_IPV4 - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP - ip6_addr_t ipv6Addr; - if (!ip6addr_aton(str, &ipv6Addr)) - return false; -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP - struct in6_addr ipv6Addr; - if (inet_pton(AF_INET6, str, &ipv6Addr) < 1) - return false; -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP - output = FromIPv6(ipv6Addr); - } - - return true; -} - -bool IPAddress::FromString(const char *str, size_t strLen, IPAddress& output) -{ - bool res = false; - - if (strLen < INET6_ADDRSTRLEN) - { - char hostNameBuf[INET6_ADDRSTRLEN]; - memcpy(hostNameBuf, str, strLen); - hostNameBuf[strLen] = 0; - res = IPAddress::FromString(hostNameBuf, output); - } - - return res; -} - - - -} // namespace Inet -} // namespace chip diff --git a/src/inet/IPAddress.cpp b/src/inet/IPAddress.cpp deleted file mode 100644 index b743ae5bdafd42..00000000000000 --- a/src/inet/IPAddress.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* - * - * - * - * 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 implements the class Inet::IPAddress and - * related enumerated constants. The Nest Inet Layer uses objects - * of this class to represent Internet protocol addresses of both - * IPv4 and IPv6 address families. (IPv4 addresses are stored - * internally in the V4COMPAT format, reserved for that purpose.) - * - */ - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif -#include -#include - -#include -#include - -#include "arpa-inet-compatibility.h" - -namespace chip { -namespace Inet { - -IPAddress IPAddress::Any; - -bool IPAddress::operator==(const IPAddress& other) const -{ - return Addr[0] == other.Addr[0] && Addr[1] == other.Addr[1] && Addr[2] == other.Addr[2] && Addr[3] == other.Addr[3]; -} - -bool IPAddress::operator!=(const IPAddress& other) const -{ - return Addr[0] != other.Addr[0] || Addr[1] != other.Addr[1] || Addr[2] != other.Addr[2] || Addr[3] != other.Addr[3]; -} - -IPAddress & IPAddress::operator=(const IPAddress& other) -{ - if (this != &other) - { - Addr[0] = other.Addr[0]; - Addr[1] = other.Addr[1]; - Addr[2] = other.Addr[2]; - Addr[3] = other.Addr[3]; - } - - return *this; -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -ip_addr_t IPAddress::ToLwIPAddr(void) const -{ - ip_addr_t ret; - - switch (Type()) - { -#if INET_CONFIG_ENABLE_IPV4 - case kIPAddressType_IPv4: - IP_SET_TYPE_VAL(ret, IPADDR_TYPE_V4); - *ip_2_ip4(&ret) = IPAddress::ToIPv4(); - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - case kIPAddressType_IPv6: - IP_SET_TYPE_VAL(ret, IPADDR_TYPE_V6); - *ip_2_ip6(&ret) = IPAddress::ToIPv6(); - break; - - default: - ret = *IP_ADDR_ANY; - break; - } - - return ret; -} - -IPAddress IPAddress::FromLwIPAddr(const ip_addr_t &addr) -{ - IPAddress ret; - - switch (IP_GET_TYPE(&addr)) - { -#if INET_CONFIG_ENABLE_IPV4 - case IPADDR_TYPE_V4: - ret = IPAddress::FromIPv4(*ip_2_ip4(&addr)); - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - case IPADDR_TYPE_V6: - ret = IPAddress::FromIPv6(*ip_2_ip6(&addr)); - break; - - default: - ret = Any; - break; - } - - return ret; -} - -lwip_ip_addr_type IPAddress::ToLwIPAddrType(IPAddressType typ) -{ - lwip_ip_addr_type ret; - - switch (typ) - { -#if INET_CONFIG_ENABLE_IPV4 - case kIPAddressType_IPv4: - ret = IPADDR_TYPE_V4; - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - case kIPAddressType_IPv6: - ret = IPADDR_TYPE_V6; - break; - - default: - ret = IPADDR_TYPE_ANY; - break; - } - - return ret; -} -#endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - -#if INET_CONFIG_ENABLE_IPV4 -ip4_addr_t IPAddress::ToIPv4() const -{ - return *(ip4_addr_t *)&Addr[3]; -} - -IPAddress IPAddress::FromIPv4(const ip4_addr_t &ipv4Addr) -{ - IPAddress ipAddr; - ipAddr.Addr[0] = 0; - ipAddr.Addr[1] = 0; - ipAddr.Addr[2] = htonl(0xFFFF); - ipAddr.Addr[3] = ipv4Addr.addr; - return ipAddr; -} -#endif // INET_CONFIG_ENABLE_IPV4 - -ip6_addr_t IPAddress::ToIPv6() const -{ - return *(ip6_addr_t *)Addr; -} - -IPAddress IPAddress::FromIPv6(const ip6_addr_t &ipv6Addr) -{ - IPAddress ipAddr; - ipAddr.Addr[0] = ipv6Addr.addr[0]; - ipAddr.Addr[1] = ipv6Addr.addr[1]; - ipAddr.Addr[2] = ipv6Addr.addr[2]; - ipAddr.Addr[3] = ipv6Addr.addr[3]; - return ipAddr; -} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if INET_CONFIG_ENABLE_IPV4 -struct in_addr IPAddress::ToIPv4() const -{ - struct in_addr ipv4Addr; - ipv4Addr.s_addr = Addr[3]; - return ipv4Addr; -} - -IPAddress IPAddress::FromIPv4(const struct in_addr &ipv4Addr) -{ - IPAddress ipAddr; - ipAddr.Addr[0] = 0; - ipAddr.Addr[1] = 0; - ipAddr.Addr[2] = htonl(0xFFFF); - ipAddr.Addr[3] = ipv4Addr.s_addr; - return ipAddr; -} -#endif // INET_CONFIG_ENABLE_IPV4 - -struct in6_addr IPAddress::ToIPv6() const -{ - return *(struct in6_addr *) &Addr; -} - -IPAddress IPAddress::FromIPv6(const struct in6_addr &ipv6Addr) -{ - IPAddress ipAddr; - ipAddr.Addr[0] = htonl(((uint32_t)ipv6Addr.s6_addr[0]) << 24 | - ((uint32_t)ipv6Addr.s6_addr[1]) << 16 | - ((uint32_t)ipv6Addr.s6_addr[2]) << 8 | - ((uint32_t)ipv6Addr.s6_addr[3])); - ipAddr.Addr[1] = htonl(((uint32_t)ipv6Addr.s6_addr[4]) << 24 | - ((uint32_t)ipv6Addr.s6_addr[5]) << 16 | - ((uint32_t)ipv6Addr.s6_addr[6]) << 8 | - ((uint32_t)ipv6Addr.s6_addr[7])); - ipAddr.Addr[2] = htonl(((uint32_t)ipv6Addr.s6_addr[8]) << 24 | - ((uint32_t)ipv6Addr.s6_addr[9]) << 16 | - ((uint32_t)ipv6Addr.s6_addr[10]) << 8 | - ((uint32_t)ipv6Addr.s6_addr[11])); - ipAddr.Addr[3] = htonl(((uint32_t)ipv6Addr.s6_addr[12]) << 24 | - ((uint32_t)ipv6Addr.s6_addr[13]) << 16 | - ((uint32_t)ipv6Addr.s6_addr[14]) << 8 | - ((uint32_t)ipv6Addr.s6_addr[15])); - return ipAddr; -} - -IPAddress IPAddress::FromSockAddr(const struct sockaddr& sockaddr) -{ -#if INET_CONFIG_ENABLE_IPV4 - if (sockaddr.sa_family == AF_INET) - return FromIPv4(((sockaddr_in *) &sockaddr)->sin_addr); -#endif // INET_CONFIG_ENABLE_IPV4 - if (sockaddr.sa_family == AF_INET6) - return FromIPv6(((sockaddr_in6 *) &sockaddr)->sin6_addr); - return Any; -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -// Is address an IPv4 address encoded in IPv6 format? -bool IPAddress::IsIPv4() const -{ - return Addr[0] == 0 && Addr[1] == 0 && Addr[2] == htonl(0xFFFF); -} - -// Is address a IPv4 multicast address? -bool IPAddress::IsIPv4Multicast(void) const -{ - return (IsIPv4() && ((ntohl(Addr[3]) & 0xF0000000U) == 0xE0000000U)); -} - -// Is address the IPv4 broadcast address? -bool IPAddress::IsIPv4Broadcast(void) const -{ - return (IsIPv4() && (Addr[3] == 0xFFFFFFFFU)); -} - -// Is address an IPv4 or IPv6 multicast address? -bool IPAddress::IsMulticast(void) const -{ - return (IsIPv6Multicast() || IsIPv4Multicast()); -} - -bool IPAddress::IsIPv6(void) const -{ - return *this != Any && !IsIPv4(); -} - -// Is address an IPv6 multicast address? -bool IPAddress::IsIPv6Multicast(void) const -{ - return (ntohl(Addr[0]) & 0xFF000000U) == 0xFF000000U; -} - -// Is address an IPv6 Global Unicast Address? -bool IPAddress::IsIPv6GlobalUnicast(void) const -{ - return (ntohl(Addr[0]) & 0xE0000000U) == 0x20000000U; -} - -// Is address an IPv6 Unique Local Address? -bool IPAddress::IsIPv6ULA() const -{ - return (ntohl(Addr[0]) & 0xFF000000U) == 0xFD000000U; -} - -// Is address an IPv6 Link-local Address? -bool IPAddress::IsIPv6LinkLocal() const -{ - return (Addr[0] == htonl(0xFE800000U) && Addr[1] == 0); -} - -// Extract the interface id from a IPv6 ULA address. Returns 0 if the address -// is not a ULA. -uint64_t IPAddress::InterfaceId() const -{ - if (IsIPv6ULA()) - return (((uint64_t) ntohl(Addr[2])) << 32) | ((uint64_t) ntohl(Addr[3])); - else - return 0; -} - -// Extract the subnet id from a IPv6 ULA address. Returns 0 if the address -// is not a ULA. -uint16_t IPAddress::Subnet() const -{ - if (IsIPv6ULA()) - return (uint16_t) ntohl(Addr[1]); - else - return 0; -} - -// Extract the global id from a IPv6 ULA address. Returns 0 if the address -// is not a ULA. -uint64_t IPAddress::GlobalId() const -{ - if (IsIPv6ULA()) - return (((uint64_t) (ntohl(Addr[0]) & 0xFFFFFF)) << 16) | ((uint64_t) (ntohl(Addr[1])) & 0xFFFF0000) >> 16; - else - return 0; -} - -IPAddressType IPAddress::Type() const -{ - if (Addr[0] == 0 && Addr[1] == 0 && Addr[2] == 0 && Addr[3] == 0) - return kIPAddressType_Any; -#if INET_CONFIG_ENABLE_IPV4 - if (Addr[0] == 0 && Addr[1] == 0 && Addr[2] == htonl(0xFFFF)) - return kIPAddressType_IPv4; -#endif // INET_CONFIG_ENABLE_IPV4 - return kIPAddressType_IPv6; -} - -// Encode IPAddress to buffer in network byte order. Buffer must have at least 128 bits of available space. -// Decoder must infer IP address type from context. -void IPAddress::WriteAddress(uint8_t *&p) const -{ - // Since each of the 32bit values in the Addr array is in network byte order, a simple - // memcpy of the entire array is sufficient while copying the address. - - memcpy(p, &Addr[0], NL_INET_IPV6_ADDR_LEN_IN_BYTES); - - p += NL_INET_IPV6_ADDR_LEN_IN_BYTES; -} - -// Decode IPAddress from buffer in network byte order. Must infer IP address type from context. -void IPAddress::ReadAddress(const uint8_t *&p, IPAddress &output) -{ - // Since we want to store the address in the output array in network byte order, a simple - // memcpy of the entire array is used to retrieve from the buffer. - - memcpy(&output.Addr[0], p, NL_INET_IPV6_ADDR_LEN_IN_BYTES); - - p += NL_INET_IPV6_ADDR_LEN_IN_BYTES; -} - -// Construct an IPv6 unique local address. -IPAddress IPAddress::MakeULA(uint64_t globalId, uint16_t subnet, uint64_t interfaceId) -{ - IPAddress addr; - - addr.Addr[0] = 0xFD000000 | (uint32_t) ((globalId & 0xFFFFFF0000ULL) >> 16); - addr.Addr[0] = htonl(addr.Addr[0]); - - addr.Addr[1] = (uint32_t) ((globalId & 0x000000FFFFULL) << 16) | subnet; - addr.Addr[1] = htonl(addr.Addr[1]); - - addr.Addr[2] = htonl((uint32_t) (interfaceId >> 32)); - addr.Addr[3] = htonl((uint32_t) (interfaceId)); - - return addr; -} - -IPAddress IPAddress::MakeLLA(uint64_t interfaceId) -{ - IPAddress addr; - - addr.Addr[0] = htonl(0xFE800000); - addr.Addr[1] = 0; - - addr.Addr[2] = htonl((uint32_t) (interfaceId >> 32)); - addr.Addr[3] = htonl((uint32_t) (interfaceId)); - - return addr; -} - -IPAddress IPAddress::MakeIPv6Multicast(uint8_t aFlags, uint8_t aScope, const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES]) -{ - const uint32_t lFlagsAndScope = (((aFlags & 0xF) << 20) | - ((aScope & 0xF) << 16)); - IPAddress addr; - - addr.Addr[0] = htonl((0xFF000000U | lFlagsAndScope) | - (aGroupId[ 0] << 8) | - (aGroupId[ 1] << 0)); - addr.Addr[1] = htonl((aGroupId[ 2] << 24) | - (aGroupId[ 3] << 16) | - (aGroupId[ 4] << 8) | - (aGroupId[ 5] << 0)); - addr.Addr[2] = htonl((aGroupId[ 6] << 24) | - (aGroupId[ 7] << 16) | - (aGroupId[ 8] << 8) | - (aGroupId[ 9] << 0)); - addr.Addr[3] = htonl((aGroupId[10] << 24) | - (aGroupId[11] << 16) | - (aGroupId[12] << 8) | - (aGroupId[13] << 0)); - - return addr; -} - -IPAddress IPAddress::MakeIPv6Multicast(uint8_t aFlags, uint8_t aScope, uint32_t aGroupId) -{ - const uint8_t lGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES] = - { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - (uint8_t)((aGroupId & 0xFF000000U) >> 24), - (uint8_t)((aGroupId & 0x00FF0000U) >> 16), - (uint8_t)((aGroupId & 0x0000FF00U) >> 8), - (uint8_t)((aGroupId & 0x000000FFU) >> 0) - }; - - return (MakeIPv6Multicast(aFlags, aScope, lGroupId)); -} - -IPAddress IPAddress::MakeIPv6WellKnownMulticast(uint8_t aScope, uint32_t aGroupId) -{ - const uint8_t lFlags = 0; - - return (MakeIPv6Multicast(lFlags, aScope, aGroupId)); -} - -IPAddress IPAddress::MakeIPv6TransientMulticast(uint8_t aFlags, uint8_t aScope, const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES]) -{ - const uint8_t lFlags = (aFlags | kIPv6MulticastFlag_Transient); - - return (MakeIPv6Multicast(lFlags, aScope, aGroupId)); -} - -IPAddress IPAddress::MakeIPv6PrefixMulticast(uint8_t aScope, uint8_t aPrefixLength, const uint64_t &aPrefix, uint32_t aGroupId) -{ - const uint8_t lReserved = 0; - const uint8_t lFlags = kIPv6MulticastFlag_Prefix; - const uint8_t lGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES] = - { - lReserved, - aPrefixLength, - (uint8_t)((aPrefix & 0xFF00000000000000ULL) >> 56), - (uint8_t)((aPrefix & 0x00FF000000000000ULL) >> 48), - (uint8_t)((aPrefix & 0x0000FF0000000000ULL) >> 40), - (uint8_t)((aPrefix & 0x000000FF00000000ULL) >> 32), - (uint8_t)((aPrefix & 0x00000000FF000000ULL) >> 24), - (uint8_t)((aPrefix & 0x0000000000FF0000ULL) >> 16), - (uint8_t)((aPrefix & 0x000000000000FF00ULL) >> 8), - (uint8_t)((aPrefix & 0x00000000000000FFULL) >> 0), - (uint8_t)((aGroupId & 0xFF000000U) >> 24), - (uint8_t)((aGroupId & 0x00FF0000U) >> 16), - (uint8_t)((aGroupId & 0x0000FF00U) >> 8), - (uint8_t)((aGroupId & 0x000000FFU) >> 0) - }; - - return (MakeIPv6TransientMulticast(lFlags, aScope, lGroupId)); -} - -IPAddress IPAddress::MakeIPv4Broadcast(void) -{ - IPAddress ipAddr; - ipAddr.Addr[0] = 0; - ipAddr.Addr[1] = 0; - ipAddr.Addr[2] = htonl(0xFFFF); - ipAddr.Addr[3] = 0xFFFFFFFF; - return ipAddr; -} - - -} // namespace Inet -} // namespace chip diff --git a/src/inet/IPAddress.h b/src/inet/IPAddress.h deleted file mode 100644 index 4c5e29b8768a9e..00000000000000 --- a/src/inet/IPAddress.h +++ /dev/null @@ -1,665 +0,0 @@ -/* - * - * - * - * 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 the class Inet::IPAddress and - * related enumerated constants. The Nest Inet Layer uses objects - * of this class to represent Internet protocol addresses of both - * IPv4 and IPv6 address families. (IPv4 addresses are stored - * internally in the V4COMPAT format, reserved for that purpose.) - */ - -#ifndef IPADDRESS_H -#define IPADDRESS_H - -#include - -#include - -#include -#include "IANAConstants.h" - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#if INET_CONFIG_ENABLE_IPV4 -#include -#endif // INET_CONFIG_ENABLE_IPV4 -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#define NL_INET_IPV6_ADDR_LEN_IN_BYTES (16) -#define NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES (14) - -/** - * @brief Adaptation for LwIP ip4_addr_t type. - * - * @details - * Before LwIP 2.0.0, the \c ip_addr_t type alias referred to a structure comprising - * an IPv4 address. At LwIP 2.0.0 and thereafter, this type alias is renamed \c ip4_addr_t - * and \c ip_addr_t is replaced with an alias to a union of both. Here, the \c ip4_addr_t - * type alias is provided even when the LwIP version is earlier than 2.0.0 so as to prepare - * for the import of the new logic. - */ -#if CHIP_SYSTEM_CONFIG_USE_LWIP && INET_CONFIG_ENABLE_IPV4 && LWIP_VERSION_MAJOR < 2 && LWIP_VERSION_MINOR < 5 -typedef ip_addr_t ip4_addr_t; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP && INET_CONFIG_ENABLE_IPV4 && LWIP_VERSION_MAJOR < 2 && LWIP_VERSION_MINOR < 5 - -#if CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_VERSION_MAJOR == 1 && LWIP_VERSION_MINOR >= 5 -typedef u8_t lwip_ip_addr_type; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_VERSION_MAJOR == 1 && LWIP_VERSION_MINOR >= 5 - -namespace chip { -namespace Inet { - -/** - * @brief Internet protocol address family - * - * @details - * Values of the \c IPAddressType type are returned by the - * IPAddress::Type() method. They indicate the address family - * entailed by the use of the address. - */ -typedef enum -{ - /** Not used. */ - kIPAddressType_Unknown = 0, - -#if INET_CONFIG_ENABLE_IPV4 - /** Internet protocol version 4. */ - kIPAddressType_IPv4 = 1, -#endif // INET_CONFIG_ENABLE_IPV4 - - /** Internet protocol version 6. */ - kIPAddressType_IPv6 = 2, - - /** The unspecified internet address (independent of protocol version) */ - kIPAddressType_Any = 3 -} IPAddressType; - -/** - * @brief Internet protocol v6 multicast flags - * - * @details - * Values of the \c IPv6MulticastFlag type are used to call the - * IPAddress::MakeIPv6Multicast() methods. They indicate the - * type of IPv6 multicast address to create. These numbers are - * registered by IETF with IANA. - */ -typedef enum -{ - /** The multicast address is (1) transient (i.e., dynamically-assigned) rather than (0) well-known (i.e, IANA-assigned). */ - kIPv6MulticastFlag_Transient = 0x01, - - /** The multicast address is (1) based on a network prefix. */ - kIPv6MulticastFlag_Prefix = 0x02 -} IPv6MulticastFlag; - -/** - * @brief Internet protocol address - * - * @details - * The Nest Inet Layer uses objects of this class to represent Internet - * protocol addresses (independent of protocol version). - */ -class DLL_EXPORT IPAddress -{ -public: - - /** - * @brief Opaque word array to contain IP addresses (independent of protocol version) - * - * @details - * IPv6 address use all 128-bits split into four 32-bit network byte - * ordered unsigned integers. IPv4 addresses are V4COMPAT, i.e. the - * first three words are zero, and the fourth word contains the IPv4 - * address in network byte order. - */ - uint32_t Addr[4]; - - /** - * @brief Test whether address is IPv6 compatible. - * - * @details - * Use this method to check if the address belongs to the IPv6 address - * family. Note well: the unspecified address is not an IPv6 address. - * - * @retval true The address is IPv6 and not the unspecified address. - * @retval false The address is IPv4 or the unspecified address. - */ - bool IsIPv6(void) const; - - /** - * @brief Test whether address is IPv6 global unicast address. - * - * @details - * Use this method to check if the address belongs to the IPv6 address - * family and has the global unicast address prefix. - * - * @retval true Address is IPv6 global unicast - * @retval false Otherwise - */ - bool IsIPv6GlobalUnicast(void) const; - - /** - * @brief Test whether address is IPv6 unique-local address (ULA). - * - * @details - * Use this method to check if the address belongs to the IPv6 address - * family and has the reserved IPv6 unique-local address prefix. - * - * @retval true Address is IPv6 unique-local - * @retval false Otherwise - */ - bool IsIPv6ULA(void) const; - - /** - * @brief Test whether address is IPv6 link-local address (LL). - * - * @details - * Use this method to check if the address belongs to the IPv6 address - * family and has the reserved IPv6 link-local address prefix. - * - * @retval true Address is IPv6 link-local - * @retval false Otherwise - */ - bool IsIPv6LinkLocal(void) const; - - /** - * @brief Test whether address is IPv6 multicast. - * - * @details - * Use this method to check if the address belongs to the IPv6 address - * family and has the reserved IPv6 multicast address prefix. - * - * @retval true Address is IPv6 multicast - * @retval false Otherwise - */ - bool IsIPv6Multicast(void) const; - - /** - * @brief Test whether address is IPv4 or IPv6 multicast. - * - * @details - * Use this method to check if the address belongs to the IPv4 or IPv6 address - * family and has the reserved IPv4 or IPv6 multicast address prefix. - * - * @retval true Address is IPv4 or IPv6 multicast - * @retval false Otherwise - */ - bool IsMulticast(void) const; - - /** - * @brief Extract the IID of an IPv6 ULA address. - * - * @details - * Use this method with an IPv6 unique-local address (ULA) to extract the - * identifier identifier (IID), which is the least significant 64 bits of - * the address. - * - * @return 64-bit interface identifier, or zero if the IP address is not - * an IPv6 unique-local address. - */ - uint64_t InterfaceId(void) const; - - /** - * @brief Extract the 16-bit subnet identifier of an IPv6 ULA address. - * - * @details - * Use this method with an IPv6 unique-local address (ULA) to extract the - * subnet identifier, which is the least significant 16 bits of the - * network prefix. The network prefix is the most significant 64 bits of - * of the address. In other words, the subnet identifier is located in - * the 7th and 8th bytes of a 16-byte address. - * - * @return 16-bit subnet identifier, or zero if the IP address is not - * an IPv6 unique-local address. - */ - uint16_t Subnet(void) const; - - /** - * @brief Extract the 16-bit global network identifier of an IPv6 ULA - * address. - * - * @details - * Use this method with an IPv6 unique-local address (ULA) to extract the - * global network identifier, which is the 40 bits immediately following - * the distinguished ULA network prefix, i.e. fd00::/8. In other words, - * the global network identifier is located in the five bytes from the 2nd - * 2nd through the 6th bytes in the address. - * - * @return 40-bit global network identifier, or zero if the IP address - * is not an IPv6 unique-local address. - */ - uint64_t GlobalId(void) const; - - /** - * @brief Extract the type of the IP address. - * - * @details - * Use this method to return an value of the enumerated type \c - * IPAddressType to indicate the type of the IP address. - * - * @retval kIPAddressType_IPv4 The address is IPv4. - * @retval kIPAddressType_IPv6 The address is IPv6. - * @retval kIPAddressType_Any The address is the unspecified address. - */ - IPAddressType Type(void) const; - - /** - * @brief Compare this IP address with another for equivalence. - * - * @param[in] other The address to compare. - * - * @retval true If equivalent to \c other - * @retval false Otherwise - */ - bool operator ==(const IPAddress& other) const; - - /** - * @brief Compare this IP address with another for inequivalence. - * - * @param[in] other The address to compare. - * - * @retval true If equivalent to \c other - * @retval false Otherwise - */ - bool operator !=(const IPAddress& other) const; - - /** - * @brief Conventional assignment operator. - * - * @param[in] other The address to copy. - * - * @return A reference to this object. - */ - IPAddress& operator =(const IPAddress& other); - - /** - * @brief Emit the IP address in conventional text presentation format. - * - * @param[out] buf The address of the emitted text. - * @param[in] bufSize The size of the buffer for the emitted text. - * - * @details - * Use ToString(char *buf, uint32_t bufSize) const to write the - * conventional text presentation form of the IP address to the memory - * located at \c buf and extending as much as \c bufSize bytes, including - * its NUL termination character. - * - * Note Well: not compliant with RFC 5952 on some platforms. Specifically, - * zero compression may not be applied according to section 4.2. - * - * @return The argument \c buf if no formatting error, or zero otherwise. - */ - char *ToString(char *buf, uint32_t bufSize) const; - - /** - * @brief Scan the IP address from its conventional presentation text. - * - * @param[in] str The address of the emitted text. - * @param[out] output The object to set to the scanned address. - * - * @details - * Use FromString(const char *str, IPAddress& output) to - * overwrite an IP address by scanning the conventional text presentation - * located at \c str. - * - * @retval true The presentation format is valid - * @retval false Otherwise - */ - static bool FromString(const char *str, IPAddress& output); - - /** - * @brief Scan the IP address from its conventional presentation text. - * - * @param[in] str A pointer to the text to be scanned. - * @param[in] strLen The length of the text to be scanned. - * @param[out] output The object to set to the scanned address. - * - * @details - * Use FromString(const char *str, size_t strLen, IPAddress& output) to - * overwrite an IP address by scanning the conventional text presentation - * located at \c str. - * - * @retval true The presentation format is valid - * @retval false Otherwise - */ - static bool FromString(const char *str, size_t strLen, IPAddress& output); - - /** - * @brief Emit the IP address in standard network representation. - * - * @param[inout] p Reference to the cursor to use for writing. - * - * @details - * Use WriteAddress(uint8_t *&p) to encode the IP address in - * the binary format defined by RFC 4291 for IPv6 addresses. IPv4 - * addresses are encoded according to section 2.5.5.1 "IPv4-Compatible - * IPv6 Address" (V4COMPAT). - */ - void WriteAddress(uint8_t *&p) const; - - /** - * @brief Emit the IP address in standard network representation. - * - * @param[inout] p Reference to the cursor to use for reading. - * @param[out] output Object to receive decoded IP address. - * - * @details - * Use ReadAddress(uint8_t *&p, IPAddress &output) to decode - * the IP address at \c p to the object \c output. - */ - static void ReadAddress(const uint8_t *&p, IPAddress &output); - - /** - * @brief Test whether address is IPv4 compatible. - * - * @details - * Use this method to check if the address belongs to the IPv4 address - * family. Note well: the unspecified address is not an IPv4 address. - * - * @retval true The address is IPv4 and not the unspecified address. - * @retval false The address is IPv6 or the unspecified address. - */ - bool IsIPv4(void) const; - - /** - * @brief Test whether address is IPv4 multicast. - * - * @details - * Use this method to check if the address is an IPv4 multicast - * address. - * - * @retval true Address is the IPv4 multicast - * @retval false Otherwise - */ - bool IsIPv4Multicast(void) const; - - /** - * @brief Test whether address is IPv4 broadcast. - * - * @details - * Use this method to check if the address is the special purpose IPv4 - * broadcast address. - * - * @retval true Address is the IPv4 broadcast - * @retval false Otherwise - */ - bool IsIPv4Broadcast(void) const; - - /** - * @fn ToIPv4() const - * - * @brief Extract the IPv4 address as a platform data structure. - * - * @details - * Use ToIPv4() const to extract the content as an IPv4 address, - * if possible. IPv6 addresses and the unspecified address are - * extracted as 0.0.0.0. - * - * The result is either of type struct in_addr (on POSIX) or - * ip4_addr_t (on LwIP). - * - * @return The encapsulated IPv4 address, or \c 0.0.0.0 if the address is - * either unspecified or not an IPv4 address. - */ - - /** - * @fn ToIPv6() const - * - * @brief Extract the IPv6 address as a platform data structure. - * - * @details - * Use ToIPv6() const to extract the content as an IPv6 address, - * if possible. IPv4 addresses and the unspecified address are extracted - * as [::]. - * - * The result is either of type struct in6_addr (on POSIX) or - * ip6_addr_t (on LwIP). - * - * @return The encapsulated IPv4 address, or \c [::] if the address is - * either unspecified or not an IPv4 address. - */ - - /** - * @fn static IPAddress FromIPv4(const struct in_addr & addr) - * - * @brief Inject the IPv4 address from a platform data structure. - * - * @details - * Use FromIPv4(const ip4_addr_t &addr) to inject \c addr as an - * IPv4 address. - * - * The argument \c addr is either of type const struct in_addr& - * (on POSIX) or const ip4_addr_t& (on LwIP). - * - * @return The constructed IP address. - */ - /** - * @overload static IPAddress FromIPv4(const ip4_addr_t &addr) - */ - - /** - * @fn static IPAddress FromIPv6(const struct in6_addr& addr) - * - * @brief Inject the IPv6 address from a platform data structure. - * - * @details - * Use FromIPv6(const ip6_addr_t &addr) to inject \c addr as an - * IPv6 address. - * - * The argument \c addr is either of type const struct in6_addr& - * (on POSIX) or const ip6_addr_t& (on LwIP). - * - * @return The constructed IP address. - */ - /** - * @overload static IPAddress FromIPv6(const ip6_addr_t &addr) - */ - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - /** - * @fn ToLwIPAddr() const - * - * @brief Extract the IP address as a LwIP ip_addr_t structure. - * - * @details - * Use ToLwIPAddr() const to extract the content as an IP address, - * if possible. - * - * @return An LwIP ip_addr_t structure corresponding to the IP address. - */ - ip_addr_t ToLwIPAddr(void) const; - - /** - * @fn static IPAddress FromLwIPAddr(const ip_addr_t& addr) - * - * @brief Inject the IP address from an LwIP ip_addr_t structure. - * - * @details - * Use FromLwIPAddr(const ip_addr_t &addr) to inject \c addr as an - * Inet layer IP address. - * - * The argument \c addr is of type const ip_addr_t& (on LwIP). - * - * @return The constructed IP address. - */ - static IPAddress FromLwIPAddr(const ip_addr_t &addr); - - /** - * @brief Convert the INET layer address type to its underlying LwIP type. - * - * @details - * Use ToLwIPAddrType(IPAddressType) to convert the IP address type - * to its underlying LwIP address type code. (LWIP_VERSION_MAJOR > 1 only). - */ - static lwip_ip_addr_type ToLwIPAddrType(IPAddressType); -#endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - - ip6_addr_t ToIPv6(void) const; - static IPAddress FromIPv6(const ip6_addr_t &addr); - -#if INET_CONFIG_ENABLE_IPV4 - ip4_addr_t ToIPv4(void) const; - static IPAddress FromIPv4(const ip4_addr_t &addr); -#endif // INET_CONFIG_ENABLE_IPV4 - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - struct in6_addr ToIPv6(void) const; - static IPAddress FromIPv6(const struct in6_addr &addr); - -#if INET_CONFIG_ENABLE_IPV4 - struct in_addr ToIPv4(void) const; - static IPAddress FromIPv4(const struct in_addr &addr); -#endif // INET_CONFIG_ENABLE_IPV4 - - /** - * @brief Inject the IPv6 address from a POSIX struct sockaddr& - * - * @details - * Use FromSockAddr(const struct sockaddr& sockaddr) to inject - * sockaddr.sa_addr as an IPv6 address. - * - * @return The constructed IP address. - */ - static IPAddress FromSockAddr(const struct sockaddr& sockaddr); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - /** - * @brief Construct an IPv6 unique-local address (ULA) from its parts. - * - * @details - * Use MakeULA(uint64_t globalId, uint16_t subnet, uint64_t - * interfaceId) to construct a unique-local address (ULA) with global - * network identifier \c globalId, subnet identifier \c subnet and - * interface identifier (IID) \c interfaceId. - * - * @return The constructed IP address. - */ - static IPAddress MakeULA(uint64_t globalId, uint16_t subnet, - uint64_t interfaceId); - - /** - * @brief Construct an IPv6 link-local address (LL) from its IID. - * - * @details - * Use MakeLLA(uint64_t interfaceId) to construct an IPv6 - * link-local address (LL) with interface identifier \c interfaceId. - * - * @return The constructed IP address. - */ - static IPAddress MakeLLA(uint64_t interfaceId); - - /** - * @brief Construct an IPv6 multicast address from its parts. - * - * @details - * Use MakeIPv6Multicast(uint8_t flags, uint8_t scope, - * uint8_t groupId[14]) to construct an IPv6 multicast - * address with \c flags for routing scope \c scope and group - * identifier octets \c groupId. - * - * @return The constructed IP address. - */ - static IPAddress MakeIPv6Multicast(uint8_t aFlags, uint8_t aScope, const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES]); - - /** - * @brief Construct an IPv6 multicast address from its parts. - * - * @details - * Use MakeIPv6Multicast(uint8_t flags, uint8_t scope, - * uint32_t groupId) to construct an IPv6 multicast - * address with \c flags for routing scope \c scope and group - * identifier \c groupId. - * - * @return The constructed IP address. - */ - static IPAddress MakeIPv6Multicast(uint8_t aFlags, uint8_t aScope, uint32_t aGroupId); - - /** - * @brief Construct a well-known IPv6 multicast address from its parts. - * - * @details - * Use MakeIPv6WellKnownMulticast(uint8_t scope, uint32_t - * groupId) to construct an IPv6 multicast address for - * routing scope \c scope and group identifier \c groupId. - * - * @return The constructed IP address. - */ - static IPAddress MakeIPv6WellKnownMulticast(uint8_t aScope, uint32_t aGroupId); - - /** - * @brief Construct a transient IPv6 multicast address from its parts. - * - * @details - * Use MakeIPv6TransientMulticast(uint8_t flags, uint8_t scope, - * uint8_t groupId[14]) to construct a transient IPv6 - * multicast address with \c flags for routing scope \c scope and - * group identifier octets \c groupId. - * - * @return The constructed IP address. - */ - static IPAddress MakeIPv6TransientMulticast(uint8_t aFlags, uint8_t aScope, const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES]); - - /** - * @brief Construct a transient, prefix IPv6 multicast address from its parts. - * - * @details - * Use MakeIPv6PrefixMulticast(uint8_t scope, uint8_t - * prefixlen, const uint64_t prefix, uint32_t groupId) to - * construct a transient, prefix IPv6 multicast address with for - * routing scope \c scope and group identifier octets \c groupId, - * qualified by the prefix \c prefix of length \c prefixlen bits. - * - * @return The constructed IP address. - */ - static IPAddress MakeIPv6PrefixMulticast(uint8_t aScope, uint8_t aPrefixLength, const uint64_t &aPrefix, uint32_t aGroupId); - - /** - * @brief Construct an IPv4 broadcast address. - * - * @return The constructed IP address. - */ - static IPAddress MakeIPv4Broadcast(void); - - /** - * @brief The distinguished unspecified IP address object. - * - * @details - * This object is used as a constant for equivalence comparisons. It must - * not be modified by users of the Nest Inet Layer. - */ - static IPAddress Any; -}; - -} // namespace Inet -} // namespace chip - -#endif // !defined(IPADDRESS_H) diff --git a/src/inet/IPEndPointBasis.cpp b/src/inet/IPEndPointBasis.cpp deleted file mode 100644 index 8db79de5e55e17..00000000000000 --- a/src/inet/IPEndPointBasis.cpp +++ /dev/null @@ -1,1124 +0,0 @@ -/* - * - * - * - * 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 header file implements the Inet::IPEndPointBasis - * class, an intermediate, non-instantiable basis class - * supporting other IP-based end points. - * - */ - -// define to ensure we have the IPV6_PKTINFO -#define __APPLE_USE_RFC_3542 - -#include "IPEndPointBasis.h" - -#include - -#include -#include -#include - -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if INET_CONFIG_ENABLE_IPV4 -#include -#endif // INET_CONFIG_ENABLE_IPV4 -#include -#include -#include -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include -#include -#include -#include -#include -#include -#if HAVE_SYS_SOCKET_H -#include -#endif // HAVE_SYS_SOCKET_H - -/* - * Some systems define both IPV6_{ADD,DROP}_MEMBERSHIP and - * IPV6_{JOIN,LEAVE}_GROUP while others only define - * IPV6_{JOIN,LEAVE}_GROUP. Prefer the "_MEMBERSHIP" flavor for - * parallelism with IPv4 and create the alias to the availabile - * definitions. - */ -#if !defined(IPV6_ADD_MEMBERSHIP) && defined(IPV6_JOIN_GROUP) -#define INET_IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#elif defined(IPV6_ADD_MEMBERSHIP) -#define INET_IPV6_ADD_MEMBERSHIP IPV6_ADD_MEMBERSHIP -#else -#error "Neither IPV6_ADD_MEMBERSHIP nor IPV6_JOIN_GROUP are defined which are required for generalized IPv6 multicast group support." -#endif // !defined(IPV6_ADD_MEMBERSHIP) && defined(IPV6_JOIN_GROUP) - -#if !defined(IPV6_DROP_MEMBERSHIP) && defined(IPV6_LEAVE_GROUP) -#define INET_IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -#elif defined(IPV6_DROP_MEMBERSHIP) -#define INET_IPV6_DROP_MEMBERSHIP IPV6_DROP_MEMBERSHIP -#else -#error "Neither IPV6_DROP_MEMBERSHIP nor IPV6_LEAVE_GROUP are defined which are required for generalized IPv6 multicast group support." -#endif // !defined(IPV6_DROP_MEMBERSHIP) && defined(IPV6_LEAVE_GROUP) -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -namespace chip { -namespace Inet { - -using chip::System::PacketBuffer; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -union PeerSockAddr -{ - sockaddr any; - sockaddr_in in; - sockaddr_in6 in6; -}; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if INET_CONFIG_ENABLE_IPV4 -#define LWIP_IPV4_ADDR_T ip4_addr_t -#define IPV4_TO_LWIPADDR(aAddress) (aAddress).ToIPv4() -#endif // INET_CONFIG_ENABLE_IPV4 -#define LWIP_IPV6_ADDR_T ip6_addr_t -#define IPV6_TO_LWIPADDR(aAddress) (aAddress).ToIPv6() - -#if !defined(RAW_FLAGS_MULTICAST_LOOP) || !defined(UDP_FLAGS_MULTICAST_LOOP) || !defined(raw_clear_flags) || !defined(raw_set_flags) || !defined(udp_clear_flags) || !defined(udp_set_flags) -#define HAVE_LWIP_MULTICAST_LOOP 0 -#else -#define HAVE_LWIP_MULTICAST_LOOP 1 -#endif // !defined(RAW_FLAGS_MULTICAST_LOOP) || !defined(UDP_FLAGS_MULTICAST_LOOP) || !defined(raw_clear_flags) || !defined(raw_set_flags) || !defined(udp_clear_flags) || !defined(udp_set_flags) -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -static INET_ERROR CheckMulticastGroupArgs(InterfaceId aInterfaceId, const IPAddress &aAddress) -{ - INET_ERROR lRetval = INET_NO_ERROR; - bool lIsPresent, lIsMulticast; - - lIsPresent = IsInterfaceIdPresent(aInterfaceId); - VerifyOrExit(lIsPresent, lRetval = INET_ERROR_UNKNOWN_INTERFACE); - - lIsMulticast = aAddress.IsMulticast(); - VerifyOrExit(lIsMulticast, lRetval = INET_ERROR_WRONG_ADDRESS_TYPE); - -exit: - return (lRetval); -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if INET_CONFIG_ENABLE_IPV4 -#if LWIP_IPV4 && LWIP_IGMP -static INET_ERROR LwIPIPv4JoinLeaveMulticastGroup(InterfaceId aInterfaceId, const IPAddress &aAddress, err_t (*aMethod)(struct netif *, const LWIP_IPV4_ADDR_T *)) -{ - INET_ERROR lRetval = INET_NO_ERROR; - err_t lStatus; - struct netif * lNetif; - LWIP_IPV4_ADDR_T lIPv4Address; - - lNetif = IPEndPointBasis::FindNetifFromInterfaceId(aInterfaceId); - VerifyOrExit(lNetif != NULL, lRetval = INET_ERROR_UNKNOWN_INTERFACE); - - lIPv4Address = IPV4_TO_LWIPADDR(aAddress); - - lStatus = aMethod(lNetif, &lIPv4Address); - - switch (lStatus) - { - - case ERR_MEM: - lRetval = INET_ERROR_NO_MEMORY; - break; - - default: - lRetval = chip::System::MapErrorLwIP(lStatus); - break; - - } - -exit: - return (lRetval); -} -#endif // LWIP_IPV4 && LWIP_IGMP -#endif // INET_CONFIG_ENABLE_IPV4 - -#if LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 -static INET_ERROR LwIPIPv6JoinLeaveMulticastGroup(InterfaceId aInterfaceId, const IPAddress &aAddress, err_t (*aMethod)(struct netif *, const LWIP_IPV6_ADDR_T *)) -{ - INET_ERROR lRetval = INET_NO_ERROR; - err_t lStatus; - struct netif * lNetif; - LWIP_IPV6_ADDR_T lIPv6Address; - - lNetif = IPEndPointBasis::FindNetifFromInterfaceId(aInterfaceId); - VerifyOrExit(lNetif != NULL, lRetval = INET_ERROR_UNKNOWN_INTERFACE); - - lIPv6Address = IPV6_TO_LWIPADDR(aAddress); - - lStatus = aMethod(lNetif, &lIPv6Address); - - switch (lStatus) - { - - case ERR_MEM: - lRetval = INET_ERROR_NO_MEMORY; - break; - - default: - lRetval = chip::System::MapErrorLwIP(lStatus); - break; - - } - -exit: - return (lRetval); -} -#endif // LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -static INET_ERROR SocketsSetMulticastLoopback(int aSocket, bool aLoopback, int aProtocol, int aOption) -{ - INET_ERROR lRetval = INET_NO_ERROR; - int lStatus; - unsigned int lValue = aLoopback; - - lStatus = setsockopt(aSocket, aProtocol, aOption, &lValue, sizeof (lValue)); - VerifyOrExit(lStatus == 0, lRetval = chip::System::MapErrorPOSIX(errno)); - -exit: - return (lRetval); -} - -static INET_ERROR SocketsSetMulticastLoopback(int aSocket, IPVersion aIPVersion, bool aLoopback) -{ - INET_ERROR lRetval; - - switch (aIPVersion) - { - - case kIPVersion_6: - lRetval = SocketsSetMulticastLoopback(aSocket, aLoopback, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); - break; - -#if INET_CONFIG_ENABLE_IPV4 - case kIPVersion_4: - lRetval = SocketsSetMulticastLoopback(aSocket, aLoopback, IPPROTO_IP, IP_MULTICAST_LOOP); - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - default: - lRetval = INET_ERROR_WRONG_ADDRESS_TYPE; - break; - - } - - return (lRetval); -} - -#if INET_CONFIG_ENABLE_IPV4 -static INET_ERROR SocketsIPv4JoinLeaveMulticastGroup(int aSocket, InterfaceId aInterfaceId, const IPAddress &aAddress, int aCommand) -{ - INET_ERROR lRetval = INET_NO_ERROR; - IPAddress lInterfaceAddress; - bool lInterfaceAddressFound = false; - struct ip_mreq lMulticastRequest; - - for (InterfaceAddressIterator lAddressIterator; lAddressIterator.HasCurrent(); lAddressIterator.Next()) - { - const IPAddress lCurrentAddress = lAddressIterator.GetAddress(); - - if (lAddressIterator.GetInterface() == aInterfaceId) - { - if (lCurrentAddress.IsIPv4()) - { - lInterfaceAddressFound = true; - lInterfaceAddress = lCurrentAddress; - break; - } - } - } - - VerifyOrExit(lInterfaceAddressFound, lRetval = INET_ERROR_ADDRESS_NOT_FOUND); - - memset(&lMulticastRequest, 0, sizeof (lMulticastRequest)); - lMulticastRequest.imr_interface = lInterfaceAddress.ToIPv4(); - lMulticastRequest.imr_multiaddr = aAddress.ToIPv4(); - - lRetval = setsockopt(aSocket, IPPROTO_IP, aCommand, &lMulticastRequest, sizeof (lMulticastRequest)); - VerifyOrExit(lRetval == 0, lRetval = chip::System::MapErrorPOSIX(errno)); - -exit: - return (lRetval); -} -#endif // INET_CONFIG_ENABLE_IPV4 - -static INET_ERROR SocketsIPv6JoinLeaveMulticastGroup(int aSocket, InterfaceId aInterfaceId, const IPAddress &aAddress, int aCommand) -{ - INET_ERROR lRetval = INET_NO_ERROR; - const int lIfIndex = static_cast(aInterfaceId); - struct ipv6_mreq lMulticastRequest; - - memset(&lMulticastRequest, 0, sizeof (lMulticastRequest)); - lMulticastRequest.ipv6mr_interface = lIfIndex; - lMulticastRequest.ipv6mr_multiaddr = aAddress.ToIPv6(); - - lRetval = setsockopt(aSocket, IPPROTO_IPV6, aCommand, &lMulticastRequest, sizeof (lMulticastRequest)); - VerifyOrExit(lRetval == 0, lRetval = chip::System::MapErrorPOSIX(errno)); - -exit: - return (lRetval); -} -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/** - * @brief Set whether IP multicast traffic should be looped back. - * - * @param[in] aIPVersion - * - * @param[in] aLoop - * - * @retval INET_NO_ERROR - * success: multicast loopback behavior set - * @retval other - * another system or platform error - * - * @details - * Set whether or not IP multicast traffic should be looped back - * to this endpoint. - * - */ -INET_ERROR IPEndPointBasis::SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) -{ - INET_ERROR lRetval = INET_ERROR_NOT_IMPLEMENTED; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_SOCKETS -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if !HAVE_LWIP_MULTICAST_LOOP -#pragma message "\n \ -The version of LwIP appears older than that required for multicast loopback support.\n \ -Please upgrade your version of LwIP for SetMulticastLoopback support." - lRetval = INET_ERROR_NOT_SUPPORTED; -#else - if (aLoopback) - { - switch (mLwIPEndPointType) - { - -#if INET_CONFIG_ENABLE_RAW_ENDPOINT - case kLwIPEndPointType_Raw: - raw_set_flags(mRaw, RAW_FLAGS_MULTICAST_LOOP); - break; -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - case kLwIPEndPointType_UDP: - udp_set_flags(mUDP, UDP_FLAGS_MULTICAST_LOOP); - break; -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - - default: - lRetval = INET_ERROR_NOT_SUPPORTED; - break; - - } - } - else - { - switch (mLwIPEndPointType) - { - -#if INET_CONFIG_ENABLE_RAW_ENDPOINT - case kLwIPEndPointType_Raw: - raw_clear_flags(mRaw, RAW_FLAGS_MULTICAST_LOOP); - break; -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - case kLwIPEndPointType_UDP: - udp_clear_flags(mUDP, UDP_FLAGS_MULTICAST_LOOP); - break; -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - - default: - lRetval = INET_ERROR_NOT_SUPPORTED; - break; - - } - } - - lRetval = INET_NO_ERROR; -#endif // !HAVE_LWIP_MULTICAST_LOOP -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsSetMulticastLoopback(mSocket, aIPVersion, aLoopback); - SuccessOrExit(lRetval); - -exit: -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_SOCKETS - return (lRetval); -} - -/** - * @brief Join an IP multicast group. - * - * @param[in] aInterfaceId the indicator of the network interface to - * add to the multicast group - * - * @param[in] aAddress the multicast group to add the - * interface to - * - * @retval INET_NO_ERROR - * success: multicast group removed - * - * @retval INET_ERROR_UNKNOWN_INTERFACE - * unknown network interface, \c aInterfaceId - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * \c aAddress is not \c kIPAddressType_IPv4 or - * \c kIPAddressType_IPv6 or is not multicast - * - * @retval other - * another system or platform error - * - * @details - * Join the endpoint to the supplied multicast group on the - * specified interface. - * - */ -INET_ERROR IPEndPointBasis::JoinMulticastGroup(InterfaceId aInterfaceId, const IPAddress &aAddress) -{ - const IPAddressType lAddrType = aAddress.Type(); - INET_ERROR lRetval = INET_ERROR_NOT_IMPLEMENTED; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = CheckMulticastGroupArgs(aInterfaceId, aAddress); - SuccessOrExit(lRetval); - - switch (lAddrType) - { - -#if INET_CONFIG_ENABLE_IPV4 - case kIPAddressType_IPv4: - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if LWIP_IPV4 && LWIP_IGMP - lRetval = LwIPIPv4JoinLeaveMulticastGroup(aInterfaceId, aAddress, igmp_joingroup_netif); -#else // LWIP_IPV4 && LWIP_IGMP -#pragma message "\n \ -Please enable LWIP_IPV4 and LWIP_IGMP for IPv4 JoinMulticastGroup and LeaveMulticastGroup support." - lRetval = INET_ERROR_NOT_SUPPORTED; -#endif // LWIP_IPV4 && LWIP_IGMP - SuccessOrExit(lRetval); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsIPv4JoinLeaveMulticastGroup(mSocket, aInterfaceId, aAddress, IP_ADD_MEMBERSHIP); - SuccessOrExit(lRetval); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - } - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - case kIPAddressType_IPv6: - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 - lRetval = LwIPIPv6JoinLeaveMulticastGroup(aInterfaceId, aAddress, mld6_joingroup_netif); -#else // LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 -#pragma message "\n \ -Please enable LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 for IPv6 JoinMulticastGroup and LeaveMulticastGroup support." - lRetval = INET_ERROR_NOT_SUPPORTED; -#endif // LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 - SuccessOrExit(lRetval); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsIPv6JoinLeaveMulticastGroup(mSocket, aInterfaceId, aAddress, INET_IPV6_ADD_MEMBERSHIP); - SuccessOrExit(lRetval); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - } - break; - - default: - lRetval = INET_ERROR_WRONG_ADDRESS_TYPE; - break; - } - -exit: -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_SOCKETS - return (lRetval); -} - -/** - * @brief Leave an IP multicast group. - * - * @param[in] aInterfaceId the indicator of the network interface to - * remove from the multicast group - * - * @param[in] aAddress the multicast group to remove the - * interface from - * - * @retval INET_NO_ERROR - * success: multicast group removed - * - * @retval INET_ERROR_UNKNOWN_INTERFACE - * unknown network interface, \c aInterfaceId - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * \c aAddress is not \c kIPAddressType_IPv4 or - * \c kIPAddressType_IPv6 or is not multicast - * - * @retval other - * another system or platform error - * - * @details - * Remove the endpoint from the supplied multicast group on the - * specified interface. - * - */ -INET_ERROR IPEndPointBasis::LeaveMulticastGroup(InterfaceId aInterfaceId, const IPAddress &aAddress) -{ - const IPAddressType lAddrType = aAddress.Type(); - INET_ERROR lRetval = INET_ERROR_NOT_IMPLEMENTED; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = CheckMulticastGroupArgs(aInterfaceId, aAddress); - SuccessOrExit(lRetval); - - switch (lAddrType) - { - -#if INET_CONFIG_ENABLE_IPV4 - case kIPAddressType_IPv4: - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if LWIP_IPV4 && LWIP_IGMP - lRetval = LwIPIPv4JoinLeaveMulticastGroup(aInterfaceId, aAddress, igmp_leavegroup_netif); -#else // LWIP_IPV4 && LWIP_IGMP -#pragma message "\n \ -Please enable LWIP_IPV4 and LWIP_IGMP for IPv4 JoinMulticastGroup and LeaveMulticastGroup support." - lRetval = INET_ERROR_NOT_SUPPORTED; -#endif // LWIP_IPV4 && LWIP_IGMP - SuccessOrExit(lRetval); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsIPv4JoinLeaveMulticastGroup(mSocket, aInterfaceId, aAddress, IP_DROP_MEMBERSHIP); - SuccessOrExit(lRetval); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - } - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - case kIPAddressType_IPv6: - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 - lRetval = LwIPIPv6JoinLeaveMulticastGroup(aInterfaceId, aAddress, mld6_leavegroup_netif); -#else // LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 -#pragma message "\n \ -Please enable LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 for IPv6 JoinMulticastGroup and LeaveMulticastGroup support." - lRetval = INET_ERROR_NOT_SUPPORTED; -#endif // LWIP_IPV6_MLD && LWIP_IPV6_ND && LWIP_IPV6 - SuccessOrExit(lRetval); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsIPv6JoinLeaveMulticastGroup(mSocket, aInterfaceId, aAddress, INET_IPV6_DROP_MEMBERSHIP); - SuccessOrExit(lRetval); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - } - break; - - default: - lRetval = INET_ERROR_WRONG_ADDRESS_TYPE; - break; - } - -exit: -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_SOCKETS - return (lRetval); -} - -void IPEndPointBasis::Init(InetLayer *aInetLayer) -{ - InitEndPointBasis(*aInetLayer); - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - mBoundIntfId = INET_NULL_INTERFACEID; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -void IPEndPointBasis::HandleDataReceived(PacketBuffer *aBuffer) -{ - if ((mState == kState_Listening) && (OnMessageReceived != NULL)) - { - const IPPacketInfo *pktInfo = GetPacketInfo(aBuffer); - - if (pktInfo != NULL) - { - const IPPacketInfo pktInfoCopy = *pktInfo; // copy the address info so that the app can free the - // PacketBuffer without affecting access to address info. - OnMessageReceived(this, aBuffer, &pktInfoCopy); - } - else - { - if (OnReceiveError != NULL) - OnReceiveError(this, INET_ERROR_INBOUND_MESSAGE_TOO_BIG, NULL); - PacketBuffer::Free(aBuffer); - } - } - else - { - PacketBuffer::Free(aBuffer); - } -} - -/** - * @brief Get LwIP IP layer source and destination addressing information. - * - * @param[in] aBuffer the packet buffer containing the IP message - * - * @returns a pointer to the address information on success; otherwise, - * NULL if there is insufficient space in the packet for - * the address information. - * - * @details - * When using LwIP information about the packet is 'hidden' in the - * reserved space before the start of the data in the packet - * buffer. This is necessary because the system layer events only - * have two arguments, which in this case are used to convey the - * pointer to the end point and the pointer to the buffer. - * - * In most cases this trick of storing information before the data - * works because the first buffer in an LwIP IP message contains - * the space that was used for the Ethernet/IP/UDP headers. However, - * given the current size of the IPPacketInfo structure (40 bytes), - * it is possible for there to not be enough room to store the - * structure along with the payload in a single packet buffer. In - * practice, this should only happen for extremely large IPv4 - * packets that arrive without an Ethernet header. - * - */ -IPPacketInfo *IPEndPointBasis::GetPacketInfo(PacketBuffer *aBuffer) -{ - uintptr_t lStart; - uintptr_t lPacketInfoStart; - IPPacketInfo * lPacketInfo = NULL; - - if (!aBuffer->EnsureReservedSize(sizeof (IPPacketInfo) + 3)) - goto done; - - lStart = (uintptr_t)aBuffer->Start(); - lPacketInfoStart = lStart - sizeof (IPPacketInfo); - - // Align to a 4-byte boundary - - lPacketInfo = reinterpret_cast(lPacketInfoStart & ~(sizeof (uint32_t) - 1)); - - done: - return (lPacketInfo); -} -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -INET_ERROR IPEndPointBasis::Bind(IPAddressType aAddressType, IPAddress aAddress, uint16_t aPort, InterfaceId aInterfaceId) -{ - INET_ERROR lRetval = INET_NO_ERROR; - - if (aAddressType == kIPAddressType_IPv6) - { - struct sockaddr_in6 sa; - - memset(&sa, 0, sizeof (sa)); - - sa.sin6_family = AF_INET6; - sa.sin6_port = htons(aPort); - sa.sin6_flowinfo = 0; - sa.sin6_addr = aAddress.ToIPv6(); - sa.sin6_scope_id = aInterfaceId; - - if (bind(mSocket, (const sockaddr *) &sa, (unsigned) sizeof (sa)) != 0) - lRetval = chip::System::MapErrorPOSIX(errno); - - // Instruct the kernel that any messages to multicast destinations should be - // sent down the interface specified by the caller. -#ifdef IPV6_MULTICAST_IF - if (lRetval == INET_NO_ERROR) - setsockopt(mSocket, IPPROTO_IPV6, IPV6_MULTICAST_IF, &aInterfaceId, sizeof (aInterfaceId)); -#endif // defined(IPV6_MULTICAST_IF) - - // Instruct the kernel that any messages to multicast destinations should be - // set with the configured hop limit value. -#ifdef IPV6_MULTICAST_HOPS - int hops = INET_CONFIG_IP_MULTICAST_HOP_LIMIT; - setsockopt(mSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof (hops)); -#endif // defined(IPV6_MULTICAST_HOPS) - } -#if INET_CONFIG_ENABLE_IPV4 - else if (aAddressType == kIPAddressType_IPv4) - { - struct sockaddr_in sa; - int enable = 1; - - memset(&sa, 0, sizeof (sa)); - - sa.sin_family = AF_INET; - sa.sin_port = htons(aPort); - sa.sin_addr = aAddress.ToIPv4(); - - if (bind(mSocket, (const sockaddr *) &sa, (unsigned) sizeof (sa)) != 0) - lRetval = chip::System::MapErrorPOSIX(errno); - - // Instruct the kernel that any messages to multicast destinations should be - // sent down the interface to which the specified IPv4 address is bound. -#ifdef IP_MULTICAST_IF - if (lRetval == INET_NO_ERROR) - setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_IF, &sa, sizeof (sa)); -#endif // defined(IP_MULTICAST_IF) - - // Instruct the kernel that any messages to multicast destinations should be - // set with the configured hop limit value. -#ifdef IP_MULTICAST_TTL - int ttl = INET_CONFIG_IP_MULTICAST_HOP_LIMIT; - setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof (ttl)); -#endif // defined(IP_MULTICAST_TTL) - - // Allow socket transmitting broadcast packets. - if (lRetval == INET_NO_ERROR) - setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, &enable, sizeof (enable)); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - lRetval = INET_ERROR_WRONG_ADDRESS_TYPE; - - return (lRetval); -} - -INET_ERROR IPEndPointBasis::BindInterface(IPAddressType aAddressType, InterfaceId aInterfaceId) -{ - INET_ERROR lRetval = INET_NO_ERROR; - -#if HAVE_SO_BINDTODEVICE - if (aInterfaceId == INET_NULL_INTERFACEID) - { - //Stop interface-based filtering. - if (setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, "", 0) == -1) - { - lRetval = chip::System::MapErrorPOSIX(errno); - } - } - else - { - //Start filtering on the passed interface. - char lInterfaceName[IF_NAMESIZE]; - - if (if_indextoname(aInterfaceId, lInterfaceName) == NULL) - { - lRetval = chip::System::MapErrorPOSIX(errno); - } - - if (lRetval == INET_NO_ERROR && setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, lInterfaceName, strlen(lInterfaceName)) == -1) - { - lRetval = chip::System::MapErrorPOSIX(errno); - } - } - - if (lRetval == INET_NO_ERROR) - mBoundIntfId = aInterfaceId; - -#else // !HAVE_SO_BINDTODEVICE - lRetval = INET_ERROR_NOT_IMPLEMENTED; -#endif // HAVE_SO_BINDTODEVICE - - return (lRetval); -} - -INET_ERROR IPEndPointBasis::SendMsg(const IPPacketInfo *aPktInfo, chip::System::PacketBuffer *aBuffer, uint16_t aSendFlags) -{ - INET_ERROR res = INET_NO_ERROR; - PeerSockAddr peerSockAddr; - struct iovec msgIOV; - uint8_t controlData[256]; - struct msghdr msgHeader; - InterfaceId intfId = aPktInfo->Interface; - - // Ensure the destination address type is compatible with the endpoint address type. - VerifyOrExit(mAddrType == aPktInfo->DestAddress.Type(), res = INET_ERROR_BAD_ARGS); - - // For now the entire message must fit within a single buffer. - VerifyOrExit(aBuffer->Next() == NULL, res = INET_ERROR_MESSAGE_TOO_LONG); - - memset(&msgHeader, 0, sizeof (msgHeader)); - - msgIOV.iov_base = aBuffer->Start(); - msgIOV.iov_len = aBuffer->DataLength(); - msgHeader.msg_iov = &msgIOV; - msgHeader.msg_iovlen = 1; - - // Construct a sockaddr_in/sockaddr_in6 structure containing the destination information. - memset(&peerSockAddr, 0, sizeof (peerSockAddr)); - msgHeader.msg_name = &peerSockAddr; - if (mAddrType == kIPAddressType_IPv6) - { - peerSockAddr.in6.sin6_family = AF_INET6; - peerSockAddr.in6.sin6_port = htons(aPktInfo->DestPort); - peerSockAddr.in6.sin6_flowinfo = 0; - peerSockAddr.in6.sin6_addr = aPktInfo->DestAddress.ToIPv6(); - peerSockAddr.in6.sin6_scope_id = aPktInfo->Interface; - msgHeader.msg_namelen = sizeof(sockaddr_in6); - } -#if INET_CONFIG_ENABLE_IPV4 - else - { - peerSockAddr.in.sin_family = AF_INET; - peerSockAddr.in.sin_port = htons(aPktInfo->DestPort); - peerSockAddr.in.sin_addr = aPktInfo->DestAddress.ToIPv4(); - msgHeader.msg_namelen = sizeof(sockaddr_in); - } -#endif // INET_CONFIG_ENABLE_IPV4 - - // If the endpoint has been bound to a particular interface, - // and the caller didn't supply a specific interface to send - // on, use the bound interface. This appears to be necessary - // for messages to multicast addresses, which under Linux - // don't seem to get sent out the correct interface, despite - // the socket being bound. - if (intfId == INET_NULL_INTERFACEID) - intfId = mBoundIntfId; - - // If the packet should be sent over a specific interface, or with a specific source - // address, construct an IP_PKTINFO/IPV6_PKTINFO "control message" to that effect - // add add it to the message header. If the local OS doesn't support IP_PKTINFO/IPV6_PKTINFO - // fail with an error. - if (intfId != INET_NULL_INTERFACEID || aPktInfo->SrcAddress.Type() != kIPAddressType_Any) - { -#if defined(IP_PKTINFO) || defined(IPV6_PKTINFO) - memset(controlData, 0, sizeof(controlData)); - msgHeader.msg_control = controlData; - msgHeader.msg_controllen = sizeof(controlData); - - struct cmsghdr *controlHdr = CMSG_FIRSTHDR(&msgHeader); - -#if INET_CONFIG_ENABLE_IPV4 - - if (mAddrType == kIPAddressType_IPv4) - { -#if defined(IP_PKTINFO) - controlHdr->cmsg_level = IPPROTO_IP; - controlHdr->cmsg_type = IP_PKTINFO; - controlHdr->cmsg_len = CMSG_LEN(sizeof(in_pktinfo)); - - struct in_pktinfo *pktInfo = (struct in_pktinfo *)CMSG_DATA(controlHdr); - pktInfo->ipi_ifindex = intfId; - pktInfo->ipi_spec_dst = aPktInfo->SrcAddress.ToIPv4(); - - msgHeader.msg_controllen = CMSG_SPACE(sizeof(in_pktinfo)); -#else // !defined(IP_PKTINFO) - ExitNow(res = INET_ERROR_NOT_SUPPORTED); -#endif // !defined(IP_PKTINFO) - } - -#endif // INET_CONFIG_ENABLE_IPV4 - - if (mAddrType == kIPAddressType_IPv6) - { -#if defined(IPV6_PKTINFO) - controlHdr->cmsg_level = IPPROTO_IPV6; - controlHdr->cmsg_type = IPV6_PKTINFO; - controlHdr->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo)); - - struct in6_pktinfo *pktInfo = (struct in6_pktinfo *)CMSG_DATA(controlHdr); - pktInfo->ipi6_ifindex = intfId; - pktInfo->ipi6_addr = aPktInfo->SrcAddress.ToIPv6(); - - msgHeader.msg_controllen = CMSG_SPACE(sizeof(in6_pktinfo)); -#else // !defined(IPV6_PKTINFO) - ExitNow(res = INET_ERROR_NOT_SUPPORTED); -#endif // !defined(IPV6_PKTINFO) - } - -#else // !(defined(IP_PKTINFO) && defined(IPV6_PKTINFO)) - - ExitNow(res = INET_ERROR_NOT_SUPPORTED); - -#endif // !(defined(IP_PKTINFO) && defined(IPV6_PKTINFO)) - } - - // Send IP packet. - { - const ssize_t lenSent = sendmsg(mSocket, &msgHeader, 0); - if (lenSent == -1) - res = chip::System::MapErrorPOSIX(errno); - else if (lenSent != aBuffer->DataLength()) - res = INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED; - } - -exit: - return (res); -} - -INET_ERROR IPEndPointBasis::GetSocket(IPAddressType aAddressType, int aType, int aProtocol) -{ - INET_ERROR res = INET_NO_ERROR; - - if (mSocket == INET_INVALID_SOCKET_FD) - { - const int one = 1; - int family; - - switch (aAddressType) - { - case kIPAddressType_IPv6: - family = PF_INET6; - break; - -#if INET_CONFIG_ENABLE_IPV4 - case kIPAddressType_IPv4: - family = PF_INET; - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - default: - return INET_ERROR_WRONG_ADDRESS_TYPE; - } - - mSocket = ::socket(family, aType, aProtocol); - if (mSocket == -1) - return chip::System::MapErrorPOSIX(errno); - - mAddrType = aAddressType; - - // NOTE WELL: the errors returned by setsockopt() here are not - // returned as Inet layer chip::System::MapErrorPOSIX(errno) - // codes because they are normally expected to fail on some - // platforms where the socket option code is defined in the - // header files but not [yet] implemented. Certainly, there is - // room to improve this by connecting the build configuration - // logic up to check for implementations of these options and - // to provide appropriate HAVE_xxxxx definitions accordingly. - - res = setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&one, sizeof (one)); - static_cast(res); - -#ifdef SO_REUSEPORT - res = setsockopt(mSocket, SOL_SOCKET, SO_REUSEPORT, (void*)&one, sizeof (one)); - if (res != 0) - { - chipLogError(Inet, "SO_REUSEPORT failed: %d", errno); - } -#endif // defined(SO_REUSEPORT) - - // If creating an IPv6 socket, tell the kernel that it will be - // IPv6 only. This makes it posible to bind two sockets to - // the same port, one for IPv4 and one for IPv6. - -#ifdef IPV6_V6ONLY - if (aAddressType == kIPAddressType_IPv6) - { - res = setsockopt(mSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &one, sizeof (one)); - if (res != 0) - { - chipLogError(Inet, "IPV6_V6ONLY failed: %d", errno); - } - } -#endif // defined(IPV6_V6ONLY) - -#if INET_CONFIG_ENABLE_IPV4 -#ifdef IP_PKTINFO - if (aAddressType == kIPAddressType_IPv4) - { - res = setsockopt(mSocket, IPPROTO_IP, IP_PKTINFO, (void *) &one, sizeof (one)); - if (res != 0) - { - chipLogError(Inet, "IP_PKTINFO failed: %d", errno); - } - } -#endif // defined(IP_PKTINFO) -#endif // INET_CONFIG_ENABLE_IPV4 - -#ifdef IPV6_RECVPKTINFO - if (aAddressType == kIPAddressType_IPv6) - { - res = setsockopt(mSocket, IPPROTO_IPV6, IPV6_RECVPKTINFO, (void *) &one, sizeof (one)); - if (res != 0) - { - chipLogError(Inet, "IPV6_PKTINFO failed: %d", errno); - } - } -#endif // defined(IPV6_RECVPKTINFO) - - // On systems that support it, disable the delivery of SIGPIPE - // signals when writing to a closed socket. This is mostly - // needed on iOS which has the peculiar habit of sending - // SIGPIPEs on unconnected UDP sockets. -#ifdef SO_NOSIGPIPE - { - res = setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof (one)); - if (res != 0) - { - chipLogError(Inet, "SO_NOSIGPIPE failed: %d", errno); - } - } -#endif // defined(SO_NOSIGPIPE) - - } - else if (mAddrType != aAddressType) - { - return INET_ERROR_INCORRECT_STATE; - } - - return INET_NO_ERROR; -} - -SocketEvents IPEndPointBasis::PrepareIO(void) -{ - SocketEvents res; - - if (mState == kState_Listening && OnMessageReceived != NULL) - res.SetRead(); - - return res; -} - -void IPEndPointBasis::HandlePendingIO(uint16_t aPort) -{ - INET_ERROR lStatus = INET_NO_ERROR; - IPPacketInfo lPacketInfo; - PacketBuffer * lBuffer; - - lPacketInfo.Clear(); - lPacketInfo.DestPort = aPort; - - lBuffer = PacketBuffer::New(0); - - if (lBuffer != NULL) - { - struct iovec msgIOV; - PeerSockAddr lPeerSockAddr; - uint8_t controlData[256]; - struct msghdr msgHeader; - - msgIOV.iov_base = lBuffer->Start(); - msgIOV.iov_len = lBuffer->AvailableDataLength(); - - memset(&lPeerSockAddr, 0, sizeof (lPeerSockAddr)); - - memset(&msgHeader, 0, sizeof (msgHeader)); - - msgHeader.msg_name = &lPeerSockAddr; - msgHeader.msg_namelen = sizeof (lPeerSockAddr); - msgHeader.msg_iov = &msgIOV; - msgHeader.msg_iovlen = 1; - msgHeader.msg_control = controlData; - msgHeader.msg_controllen = sizeof (controlData); - - ssize_t rcvLen = recvmsg(mSocket, &msgHeader, MSG_DONTWAIT); - - if (rcvLen < 0) - { - lStatus = chip::System::MapErrorPOSIX(errno); - } - else if (rcvLen > lBuffer->AvailableDataLength()) - { - lStatus = INET_ERROR_INBOUND_MESSAGE_TOO_BIG; - } - else - { - lBuffer->SetDataLength((uint16_t) rcvLen); - - if (lPeerSockAddr.any.sa_family == AF_INET6) - { - lPacketInfo.SrcAddress = IPAddress::FromIPv6(lPeerSockAddr.in6.sin6_addr); - lPacketInfo.SrcPort = ntohs(lPeerSockAddr.in6.sin6_port); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (lPeerSockAddr.any.sa_family == AF_INET) - { - lPacketInfo.SrcAddress = IPAddress::FromIPv4(lPeerSockAddr.in.sin_addr); - lPacketInfo.SrcPort = ntohs(lPeerSockAddr.in.sin_port); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - { - lStatus = INET_ERROR_INCORRECT_STATE; - } - } - - if (lStatus == INET_NO_ERROR) - { - for (struct cmsghdr *controlHdr = CMSG_FIRSTHDR(&msgHeader); - controlHdr != NULL; - controlHdr = CMSG_NXTHDR(&msgHeader, controlHdr)) - { -#if INET_CONFIG_ENABLE_IPV4 -#ifdef IP_PKTINFO - if (controlHdr->cmsg_level == IPPROTO_IP && controlHdr->cmsg_type == IP_PKTINFO) - { - struct in_pktinfo *inPktInfo = (struct in_pktinfo *)CMSG_DATA(controlHdr); - lPacketInfo.Interface = inPktInfo->ipi_ifindex; - lPacketInfo.DestAddress = IPAddress::FromIPv4(inPktInfo->ipi_addr); - continue; - } -#endif // defined(IP_PKTINFO) -#endif // INET_CONFIG_ENABLE_IPV4 - -#ifdef IPV6_PKTINFO - if (controlHdr->cmsg_level == IPPROTO_IPV6 && controlHdr->cmsg_type == IPV6_PKTINFO) - { - struct in6_pktinfo *in6PktInfo = (struct in6_pktinfo *)CMSG_DATA(controlHdr); - lPacketInfo.Interface = in6PktInfo->ipi6_ifindex; - lPacketInfo.DestAddress = IPAddress::FromIPv6(in6PktInfo->ipi6_addr); - continue; - } -#endif // defined(IPV6_PKTINFO) - } - } - } - else - { - lStatus = INET_ERROR_NO_MEMORY; - } - - if (lStatus == INET_NO_ERROR) - OnMessageReceived(this, lBuffer, &lPacketInfo); - else - { - PacketBuffer::Free(lBuffer); - if (OnReceiveError != NULL - && lStatus != chip::System::MapErrorPOSIX(EAGAIN) - ) - OnReceiveError(this, lStatus, NULL); - } - - return; -} -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -} // namespace Inet -} // namespace chip diff --git a/src/inet/IPEndPointBasis.h b/src/inet/IPEndPointBasis.h deleted file mode 100644 index a8211e05ee6000..00000000000000 --- a/src/inet/IPEndPointBasis.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * - * - * - * 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 header file defines the Inet::IPEndPointBasis - * class, an intermediate, non-instantiable basis class - * supporting other IP-based end points. - * - */ - -#ifndef IPENDPOINTBASIS_H -#define IPENDPOINTBASIS_H - -#include - -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -namespace chip { -namespace Inet { - -class InetLayer; -class IPPacketInfo; - -/** - * @class IPEndPointBasis - * - * @brief Objects of this class represent non-instantiable IP protocol - * endpoints. - * - */ -class DLL_EXPORT IPEndPointBasis : public EndPointBasis -{ - friend class InetLayer; - -public: - /** - * @brief Basic dynamic state of the underlying endpoint. - * - * @details - * Objects are initialized in the "ready" state, proceed to the "bound" - * state after binding to a local interface address, then proceed to the - * "listening" state when they have continuations registered for handling - * events for reception of ICMP messages. - * - * @note - * The \c kBasisState_Closed state enumeration is mapped to \c - * kState_Ready for historical binary-compatibility reasons. The - * existing \c kState_Closed exists to identify separately the - * distinction between "not opened yet" and "previously opened - * now closed" that existed previously in the \c kState_Ready and - * \c kState_Closed states. - */ - enum { - kState_Ready = kBasisState_Closed, /**< Endpoint initialized, but not open. */ - kState_Bound = 1, /**< Endpoint bound, but not listening. */ - kState_Listening = 2, /**< Endpoint receiving datagrams. */ - kState_Closed = 3 /**< Endpoint closed, ready for release. */ - } mState; - - /** - * @brief Transmit option flags for the \c SendMsg method. - */ - enum { - /** Do not destructively queue the message directly. Queue a copy. */ - kSendFlag_RetainBuffer = 0x0040 - }; - - /** - * @brief Type of message text reception event handling function. - * - * @param[in] endPoint The endpoint associated with the event. - * @param[in] msg The message text received. - * @param[in] senderAddr The IP address of the sender. - * - * @details - * Provide a function of this type to the \c OnMessageReceived delegate - * member to process message text reception events on \c endPoint where - * \c msg is the message text received from the sender at \c senderAddr. - */ - typedef void (*OnMessageReceivedFunct)(IPEndPointBasis *endPoint, chip::System::PacketBuffer *msg, const IPPacketInfo *pktInfo); - - /** The endpoint's message reception event handling function delegate. */ - OnMessageReceivedFunct OnMessageReceived; - - /** - * @brief Type of reception error event handling function. - * - * @param[in] endPoint The endpoint associated with the event. - * @param[in] err The reason for the error. - * - * @details - * Provide a function of this type to the \c OnReceiveError delegate - * member to process reception error events on \c endPoint. The \c err - * argument provides specific detail about the type of the error. - */ - typedef void (*OnReceiveErrorFunct)(IPEndPointBasis *endPoint, INET_ERROR err, const IPPacketInfo *pktInfo); - - /** The endpoint's receive error event handling function delegate. */ - OnReceiveErrorFunct OnReceiveError; - - INET_ERROR SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback); - INET_ERROR JoinMulticastGroup(InterfaceId aInterfaceId, const IPAddress &aAddress); - INET_ERROR LeaveMulticastGroup(InterfaceId aInterfaceId, const IPAddress &aAddress); - -protected: - void Init(InetLayer *aInetLayer); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -public: - static struct netif *FindNetifFromInterfaceId(InterfaceId aInterfaceId); - -protected: - void HandleDataReceived(chip::System::PacketBuffer *aBuffer); - - static IPPacketInfo *GetPacketInfo(chip::System::PacketBuffer *buf); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -protected: - InterfaceId mBoundIntfId; - - INET_ERROR Bind(IPAddressType aAddressType, IPAddress aAddress, uint16_t aPort, InterfaceId aInterfaceId); - INET_ERROR BindInterface(IPAddressType aAddressType, InterfaceId aInterfaceId); - INET_ERROR SendMsg(const IPPacketInfo *aPktInfo, chip::System::PacketBuffer *aBuffer, uint16_t aSendFlags); - INET_ERROR GetSocket(IPAddressType aAddressType, int aType, int aProtocol); - SocketEvents PrepareIO(void); - void HandlePendingIO(uint16_t aPort); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -private: - IPEndPointBasis(void); // not defined - IPEndPointBasis(const IPEndPointBasis &); // not defined - ~IPEndPointBasis(void); // not defined -}; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -inline struct netif *IPEndPointBasis::FindNetifFromInterfaceId(InterfaceId aInterfaceId) -{ - struct netif *lRetval = NULL; - -#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 0 && defined(NETIF_FOREACH) - NETIF_FOREACH(lRetval) - { - if (lRetval == aInterfaceId) - break; - } -#else // LWIP_VERSION_MAJOR < 2 || !defined(NETIF_FOREACH) - for (lRetval = netif_list; lRetval != NULL && lRetval != aInterfaceId; lRetval = lRetval->next); -#endif // LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 0 && defined(NETIF_FOREACH) - - return (lRetval); -} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - - -} // namespace Inet -} // namespace chip - -#endif // !defined(IPENDPOINT_H) diff --git a/src/inet/IPPrefix.cpp b/src/inet/IPPrefix.cpp deleted file mode 100644 index 4c0da4ba0340c9..00000000000000 --- a/src/inet/IPPrefix.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * - * - * 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 implements the concrete class - * Inet::IPPrefix, which comprise two member fields: - * a) a IP address and b) a length field. The Nest Inet Layer - * uses objects of this class to represent Internet protocol - * address prefixes of both IPv4 and IPv6 address families. - * - */ - -#include "IPPrefix.h" -#include - -namespace chip { -namespace Inet { - -IPPrefix IPPrefix::Zero; - -bool IPPrefix::IsZero() const -{ - return IPAddr.Addr[0] == 0 && - IPAddr.Addr[1] == 0 && - IPAddr.Addr[2] == 0 && - IPAddr.Addr[3] == 0 && - Length == 0; -} - -bool IPPrefix::operator==(const IPPrefix& other) const -{ - return IPAddr == other.IPAddr && Length == other.Length; -} - -bool IPPrefix::operator!=(const IPPrefix& other) const -{ - return IPAddr != other.IPAddr || Length != other.Length; -} - -IPPrefix & IPPrefix::operator=(const IPPrefix& other) -{ - if (this != &other) - { - IPAddr = other.IPAddr; - Length = other.Length; - } - - return *this; -} - -bool IPPrefix::MatchAddress(const IPAddress& addr) const -{ - uint8_t l = (Length <= 128) ? Length : 128; - int i; - - for (i = 0; l >= 32; i++, l -= 32) - if (IPAddr.Addr[i] != addr.Addr[i]) - return false; - - if (l == 0) - return true; - - uint32_t mask = chip::Encoding::BigEndian::HostSwap32(0xFFFFFFFF << (32 - l)); - return (IPAddr.Addr[i] & mask) == (addr.Addr[i] & mask); -} - -} // namespace Inet -} // namespace chip diff --git a/src/inet/IPPrefix.h b/src/inet/IPPrefix.h deleted file mode 100644 index 49c1dcdc25a099..00000000000000 --- a/src/inet/IPPrefix.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * - * - * 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 the concrete class - * Inet::IPPrefix, which comprise two member fields: - * a) a IP address and b) a length field. The Nest Inet Layer - * uses objects of this class to represent Internet protocol - * address prefixes of both IPv4 and IPv6 address families. - */ - -#ifndef IPPREFIX_H -#define IPPREFIX_H - -#include - -#define CHIP_INET_IPV6_DEFAULT_PREFIX_LEN (64) -#define CHIP_INET_IPV6_MAX_PREFIX_LEN (128) - -namespace chip { -namespace Inet { - -/** - * @brief Internet protocol address prefix - * - * @details - * Use objects of the \c IPPrefix class to represent Internet protocol address - * prefixes of both IPv4 and IPv6 address families. - */ -class IPPrefix -{ -public: - /** An IPv6 or IPv4 address. */ - IPAddress IPAddr; - - /** - * @brief Length of the prefix. - * - * @details - * Note well: this field is public, and it is an invariant of this class - * that Length <= 32 where the type of \c IPAddr is - * \c kIPAddressType_IPv4 and Length <= 128 where the type of - * \c IPAddr is \c kIPAddressType_IPv6. - */ - uint8_t Length; - - /** - * A distinguished object where the type of \c IPAddr is - * \c kIPAddressType_Any and Length == 0. - */ - static IPPrefix Zero; - - /** - * @brief Compares the prefix with the distinguished \c Zero value. - * - * @details - * Note well: a prefix is not equivalent to \c Zero if the type of - * \c IPAddr is not \c kIPAddressType_Any. - * - * @return \c true if equivalent to \c Zero, else \c false. - */ - bool IsZero(void) const; - - /** - * @brief Compares the prefix with another for equivalence. - * - * @details - * Note well: two prefixes are not equivalent unless the \c IPAddr fields - * are completely equivalent, i.e. all 128 bits must be identical. - * - * @return \c true if equivalent, else \c false. - */ - bool operator ==(const IPPrefix& other) const; - - /** - * @brief Compares the prefix with another for inequivalence. - * - * @details - * Note well: two prefixes are not equivalent unless the \c IPAddr fields - * are completely equivalent, i.e. all 128 bits must be identical. - * - * @return \c false if equivalent, else \c false. - */ - bool operator !=(const IPPrefix& other) const; - - /** - * @brief Conventional assignment operator. - * - * @param[in] other the prefix to copy. - * - * @return a reference to this object. - */ - IPPrefix& operator =(const IPPrefix& other); - - /** - * @brief Test if an address matches the prefix. - * - * @param[in] addr the address to test. - * - * @return \c true if \c addr has the prefix, else \c false. - */ - bool MatchAddress(const IPAddress& addr) const; -}; - -} // namespace Inet -} // namespace chip - -#endif // !defined(IPPREFIX_H) diff --git a/src/inet/Inet.h b/src/inet/Inet.h deleted file mode 100644 index d8d732e023334e..00000000000000 --- a/src/inet/Inet.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * - * - * 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 is an umbrella header for the Inet library, a - * portable Internet Protocol (IP) network interface. - * - */ - -#ifndef INET_H -#define INET_H - -#include -#include -#include -#include -#include -#include -#include "IPPrefix.h" - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#include "InetBuffer.h" -#include "InetTimer.h" -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -#if INET_CONFIG_ENABLE_DNS_RESOLVER -#include -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER - -#if INET_CONFIG_ENABLE_RAW_ENDPOINT -#include "RawEndPoint.h" -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT -#include "TCPEndPoint.h" -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT -#include "UDPEndPoint.h" -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -#if INET_CONFIG_ENABLE_TUN_ENDPOINT -#include "TunEndPoint.h" -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT - -#endif // !defined(INET_H) diff --git a/src/inet/InetBuffer.h b/src/inet/InetBuffer.h deleted file mode 100644 index 65ec192b50f00a..00000000000000 --- a/src/inet/InetBuffer.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * - * - * 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 - * Header file for the obsolescent InetBuffer type definition, which - * provides transitional definitions that source-code compatible with - * implementations that rely on the legacy InetBuffer class. - */ - -#ifndef INETBUFFER_H -#define INETBUFFER_H - -#include - -#if !INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -#error "#include // while !INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES." - -#else // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#include - -namespace chip { -namespace Inet { - -typedef chip::System::PacketBuffer InetBuffer; - -#if !CHIP_SYSTEM_CONFIG_USE_LWIP -struct pbuf : public chip::System::pbuf { }; -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP - -} // namespace Inet -} // namespace chip - -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#endif // !defined(INETBUFFER_H) diff --git a/src/inet/InetConfig.h b/src/inet/InetConfig.h deleted file mode 100644 index 8044e10f08e6f0..00000000000000 --- a/src/inet/InetConfig.h +++ /dev/null @@ -1,730 +0,0 @@ -/* - * - * - * - * 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 default compile-time configuration constants - * for the Nest InetLayer, an Internet Protocol communications - * abstraction layer. - * - * Package integrators that wish to override these values should - * either use preprocessor definitions or create a project- - * specific InetProjectConfig.h header and then assert - * HAVE_INETPROJECTCONFIG_H via the package configuration tool - * via --with-weave-inet-project-includes=DIR where DIR is the - * directory that contains the header. - * - * NOTE WELL: On some platforms, this header is included by C-language programs. - * - */ - -#ifndef INETCONFIG_H -#define INETCONFIG_H - -/*--- Include configuration headers ---*/ -#include - -/* - * If the CHIP_SYSTEM_CONFIG_TRANSFER_INETLAYER_PROJECT_CONFIGURATION option is not applicable, then the "InetProjectConfig.h" - * header was not included by and therefore it must be included here. - */ -#if !CHIP_SYSTEM_CONFIG_TRANSFER_INETLAYER_PROJECT_CONFIGURATION - -/* Include a project-specific configuration file, if defined. - * - * An application or module that incorporates chip can define a project configuration - * file to override standard Inet Layer configuration with application-specific values. - * The project config file is typically located outside the Openchip source tree, - * alongside the source code for the application. - */ -#ifdef INET_PROJECT_CONFIG_INCLUDE -#include INET_PROJECT_CONFIG_INCLUDE -#endif // INET_PROJECT_CONFIG_INCLUDE - -#endif // !CHIP_SYSTEM_CONFIG_TRANSFER_INETLAYER_PROJECT_CONFIGURATION - -/* Include a platform-specific configuration file, if defined. - * - * A platform configuration file contains overrides to standard Inet Layer configuration - * that are specific to the platform or OS on which chip is running. It is typically - * provided as apart of an adaptation layer that adapts Openchip to the target - * environment. This adaptation layer may be included in the Openchip source tree - * itself or implemented externally. - */ -#ifdef INET_PLATFORM_CONFIG_INCLUDE -#include INET_PLATFORM_CONFIG_INCLUDE -#endif - -// clang-format off - -/** - * @def INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - * - * @brief - * This boolean configuration option is (1) if the obsolescent interfaces - * of the INET layer that now reside elsewhere, for example, in the chip System - * Layer are aliased for transitional purposes. - * - */ -#ifndef INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#define INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES 0 -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES && !CHIP_SYSTEM_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#error "REQUIRED: if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES then CHIP_SYSTEM_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES!" -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES && !CHIP_SYSTEM_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -/** - * @def INET_CONFIG_MAX_IP_AND_UDP_HEADER_SIZE - * - * @brief - * The maximum space required for IPv6 and UDP headers. - * Useful when ensuring a chip message will not exceed a UDP MTU. - * - */ -#ifndef INET_CONFIG_MAX_IP_AND_UDP_HEADER_SIZE -#define INET_CONFIG_MAX_IP_AND_UDP_HEADER_SIZE (40 + 8) -#endif // INET_CONFIG_MAX_IP_AND_UDP_HEADER_SIZE - -/** - * @def INET_CONFIG_ERROR_TYPE - * - * @brief - * This defines the data type used to represent errors for the - * InetLayer subsystem. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_ERROR_TYPE. - * - */ -#ifndef INET_CONFIG_ERROR_TYPE -#define INET_CONFIG_ERROR_TYPE CHIP_SYSTEM_CONFIG_ERROR_TYPE -#endif // !defined(INET_CONFIG_ERROR_TYPE) - -/** - * @def INET_CONFIG_NO_ERROR - * - * @brief - * This defines the InetLayer error code for no error or success. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_NO_ERROR. - * - */ -#ifndef INET_CONFIG_NO_ERROR -#define INET_CONFIG_NO_ERROR CHIP_SYSTEM_CONFIG_NO_ERROR -#endif // !defined(INET_CONFIG_NO_ERROR) - -/** - * @def INET_CONFIG_ERROR_MIN - * - * @brief - * This defines the base or minimum InetLayer error number range. - * - */ -#ifndef INET_CONFIG_ERROR_MIN -#define INET_CONFIG_ERROR_MIN 1000 -#endif // INET_CONFIG_ERROR_MIN - -/** - * @def INET_CONFIG_ERROR_MAX - * - * @brief - * This defines the top or maximum InetLayer error number range. - * - */ -#ifndef INET_CONFIG_ERROR_MAX -#define INET_CONFIG_ERROR_MAX 1999 -#endif // INET_CONFIG_ERROR_MAX - -/** - * @def _INET_CONFIG_ERROR - * - * @brief - * This defines a mapping function for InetLayer errors that allows - * mapping such errors into a platform- or system-specific range. - * - */ -#ifndef _INET_CONFIG_ERROR -#define _INET_CONFIG_ERROR(e) (INET_ERROR_MIN + (e)) -#endif // _INET_CONFIG_ERROR - -/** - * @def INET_CONFIG_WILL_OVERRIDE_OS_ERROR_FUNCS - * - * @brief - * This defines whether (1) or not (0) your platform will override - * the platform- and system-specific INET_MapOSError, - * INET_DescribeOSError, and INET_IsOSError functions. - * - */ -#ifndef INET_CONFIG_WILL_OVERRIDE_OS_ERROR_FUNCS -#define INET_CONFIG_WILL_OVERRIDE_OS_ERROR_FUNCS 0 -#endif // INET_CONFIG_WILL_OVERRIDE_OS_ERROR_FUNCS - -/** - * @def INET_CONFIG_WILL_OVERRIDE_LWIP_ERROR_FUNCS - * - * @brief - * This defines whether (1) or not (0) your platform will override - * the platform- and system-specific INET_MapLwIPError, - * INET_DescribeLwIPError, and INET_IsLwIPError functions. - * - */ -#ifndef INET_CONFIG_WILL_OVERRIDE_LWIP_ERROR_FUNCS -#define INET_CONFIG_WILL_OVERRIDE_LWIP_ERROR_FUNCS 0 -#endif // INET_CONFIG_WILL_OVERRIDE_LWIP_ERROR_FUNCS - -/** - * @def INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS - * - * @brief - * This defines whether (1) or not (0) your platform will override - * the platform- and system-specific InetLayer WillInit, DidInit, - * WillShutdown, and DidShutdown. - * - */ -#ifndef INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS -#define INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS 0 -#endif // INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS - -/** - * @def INET_CONFIG_MAX_DROPPABLE_EVENTS - * - * @brief - * This is the maximum number of UDP or raw network transport - * packet events / messages that may be dropped due to packet - * buffer starvation. - * - * 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. - * - */ -#ifndef INET_CONFIG_MAX_DROPPABLE_EVENTS -#define INET_CONFIG_MAX_DROPPABLE_EVENTS 0 -#endif // INET_CONFIG_MAX_DROPPABLE_EVENTS - -/** - * @def INET_CONFIG_NUM_RAW_ENDPOINTS - * - * @brief - * This is the total number of "raw" (direct-IP, non-TCP/-UDP) end - * point context structures. - * - * Up to this many outstanding "raw" communication flows may be in - * use. - * - */ -#ifndef INET_CONFIG_NUM_RAW_ENDPOINTS -#define INET_CONFIG_NUM_RAW_ENDPOINTS 8 -#endif // INET_CONFIG_NUM_RAW_ENDPOINTS - -/** - * @def INET_CONFIG_NUM_TCP_ENDPOINTS - * - * @brief - * This is the total number of TCP end point context structures. - * - * Up to this many outstanding TCP communication flows may be in - * use. - * - */ -#ifndef INET_CONFIG_NUM_TCP_ENDPOINTS -#define INET_CONFIG_NUM_TCP_ENDPOINTS 64 -#endif // INET_CONFIG_NUM_TCP_ENDPOINTS - -/** - * @def INET_CONFIG_NUM_UDP_ENDPOINTS - * - * @brief - * This is the total number of UDP end point context structures. - * - * Up to this many outstanding UDP communication flows may be in - * use. - * - */ -#ifndef INET_CONFIG_NUM_UDP_ENDPOINTS -#define INET_CONFIG_NUM_UDP_ENDPOINTS 64 -#endif // INET_CONFIG_NUM_UDP_ENDPOINTS - -/** - * @def INET_CONFIG_NUM_TUN_ENDPOINTS - * - * @brief - * This is the total number of TUN end point context structures. - * - * Up to this many outstanding TUN endpoints may be instantiated. - * - */ -#ifndef INET_CONFIG_NUM_TUN_ENDPOINTS -#define INET_CONFIG_NUM_TUN_ENDPOINTS 64 -#endif // INET_CONFIG_NUM_TUN_ENDPOINTS - -/** - * @def INET_CONFIG_NUM_DNS_RESOLVERS - * - * @brief - * This is the total number of outstanding DNS resolution request - * contexts. - * - * Up to this many DNS resolution requests may be in in use. - * - */ -#ifndef INET_CONFIG_NUM_DNS_RESOLVERS -#define INET_CONFIG_NUM_DNS_RESOLVERS 4 -#endif // INET_CONFIG_NUM_DNS_RESOLVERS - -/** - * @def INET_CONFIG_MAX_DNS_ADDRS - * - * @brief - * This is the maximum allowable number of addresses that may - * be returned in a single DNS hostname lookup. - * - */ -#ifndef INET_CONFIG_MAX_DNS_ADDRS -#define INET_CONFIG_MAX_DNS_ADDRS 16 -#endif // INET_CONFIG_MAX_DNS_ADDRS - -/** - * @def INET_TCP_IDLE_CHECK_INTERVAL - * - * @brief - * This is the interval, in milliseconds, at which checks are made - * to detect idle TCP connections. - * - */ -#ifndef INET_TCP_IDLE_CHECK_INTERVAL -#define INET_TCP_IDLE_CHECK_INTERVAL 100 -#endif // INET_TCP_IDLE_CHECK_INTERVAL - -/** - * @def INET_CONFIG_ENABLE_DNS_RESOLVER - * - * @brief - * Defines whether (1) or not (0) to enable the ability - * to instantiate the DNS resolver. - * - */ -#ifndef INET_CONFIG_ENABLE_DNS_RESOLVER -#define INET_CONFIG_ENABLE_DNS_RESOLVER 0 -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER - -/** - * @def INET_CONFIG_ENABLE_RAW_ENDPOINT - * - * @brief - * Defines whether (1) or not (0) to enable the ability - * to instantiate a Raw endpoint. - * - */ -#ifndef INET_CONFIG_ENABLE_RAW_ENDPOINT -#define INET_CONFIG_ENABLE_RAW_ENDPOINT 0 -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -/** - * @def INET_CONFIG_ENABLE_TCP_ENDPOINT - * - * @brief - * Defines whether (1) or not (0) to enable the ability - * to instantiate a TCP endpoint. - * - */ -#ifndef INET_CONFIG_ENABLE_TCP_ENDPOINT -#define INET_CONFIG_ENABLE_TCP_ENDPOINT 0 -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -/** - * @def INET_CONFIG_ENABLE_TUN_ENDPOINT - * - * @brief - * Defines whether (1) or not (0) to enable the ability - * to instantiate a Tunnel endpoint for tun interfaces. - * By default, set when LWIP is enabled or being built - * on a Linux platform. - * - */ -#ifndef INET_CONFIG_ENABLE_TUN_ENDPOINT -#define INET_CONFIG_ENABLE_TUN_ENDPOINT 0 -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT - - -/** - * @def INET_CONFIG_ENABLE_UDP_ENDPOINT - * - * @brief - * Defines whether (1) or not (0) to enable the ability - * to instantiate a UDP endpoint. - * - */ -#ifndef INET_CONFIG_ENABLE_UDP_ENDPOINT -#define INET_CONFIG_ENABLE_UDP_ENDPOINT 0 -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -/** - * @def INET_CONFIG_EVENT_RESERVED - * - * @brief - * This defines the first number in the default chip System Layer event code space reserved for use by the Inet Layer. - * Event codes used by each layer must not overlap. - */ -#ifndef INET_CONFIG_EVENT_RESERVED -#define INET_CONFIG_EVENT_RESERVED 1000 -#endif /* INET_CONFIG_EVENT_RESERVED */ - -/** - * @def _INET_CONFIG_EVENT - * - * @brief - * This defines a mapping function for InetLayer event types that allows - * mapping such event types into a platform- or system-specific range. - * - * @note - * By default, this definition is a copy of _CHIP_SYSTEM_CONFIG_LWIP_EVENT. - * - */ -#ifndef _INET_CONFIG_EVENT -#define _INET_CONFIG_EVENT(e) _CHIP_SYSTEM_CONFIG_LWIP_EVENT(INET_CONFIG_EVENT_RESERVED + (e)) -#endif // _INET_CONFIG_EVENT - -/* - * NOTE WELL: the following configuration parameters and macro definitions are - * obsolescent. They are provided here to facilitate transition. - */ -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -/** - * @def INET_LWIP - * - * @brief - * Use LwIP. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_USE_LWIP. - */ -#ifndef INET_LWIP -#define INET_LWIP CHIP_SYSTEM_CONFIG_USE_LWIP -#endif // !defined(INET_LWIP) - -/** - * @def INET_SOCKETS - * - * @brief - * Use BSD sockets. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_USE_SOCKETS. - */ -#ifndef INET_SOCKETS -#define INET_SOCKETS CHIP_SYSTEM_CONFIG_USE_SOCKETS -#endif // !defined(INET_SOCKETS) - -/** - * @def INET_CONFIG_POSIX_LOCKING - * - * @brief - * Use POSIX locking. This is enabled by default when not compiling - * for BSD sockets. - * - * Unless you are simulating an LwIP-based system on a Unix-style - * host, this value should be left at its default. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_POSIX_LOCKING. - * - */ -#ifndef INET_CONFIG_POSIX_LOCKING -#define INET_CONFIG_POSIX_LOCKING CHIP_SYSTEM_CONFIG_POSIX_LOCKING -#endif // !defined(INET_CONFIG_POSIX_LOCKING) - -/** - * @def INET_CONFIG_FREERTOS_LOCKING - * - * @brief - * Use FreeRTOS locking. - * - * This should be generally asserted (1) for FreeRTOS + LwIP-based - * systems and deasserted (0) for BSD sockets-based systems. - * - * However, if you are simulating an LwIP-based system atop POSIX - * threads and BSD sockets, this should also be deasserted (0). - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING. - * - */ -#ifndef INET_CONFIG_FREERTOS_LOCKING -#define INET_CONFIG_FREERTOS_LOCKING CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING -#endif // !defined(INET_CONFIG_FREERTOS_LOCKING) - -/** - * @def INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS - * - * @brief - * This defines whether (1) or not (0) your platform will override - * the platform- and system-specific PostEvent, DispatchEvents, and - * DispatchEvent functions. - * - */ -#ifndef INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS -#define INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS 0 -#endif // INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS - -/** - * @def INET_CONFIG_EVENT_TYPE - * - * @brief - * This defines the type for InetEvent types, typically - * an integral type. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_LWIP_EVENT_TYPE. - * - */ -#ifndef INET_CONFIG_EVENT_TYPE -#define INET_CONFIG_EVENT_TYPE CHIP_SYSTEM_CONFIG_LWIP_EVENT_TYPE -#endif // INET_CONFIG_EVENT_TYPE - -/** - * @def INET_CONFIG_EVENT_OBJECT_TYPE - * - * @brief - * This defines the type of InetEvent objects or "messages". - * - * Such types are not directly used by the InetLayer but are - * "passed through". Consequently a forward declaration and a - * const pointer or reference are appropriate. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_LWIP_EVENT_OBJECT_TYPE. - * - */ -#ifndef INET_CONFIG_EVENT_OBJECT_TYPE -#define INET_CONFIG_EVENT_OBJECT_TYPE CHIP_SYSTEM_CONFIG_LWIP_EVENT_OBJECT_TYPE -#endif // INET_CONFIG_EVENT_OBJECT_TYPE - -/** - * @def INET_CONFIG_NUM_BUFS - * - * @brief - * This is the total number of packet buffers for the BSD sockets - * configuration. - * - * This may be set to zero (0) to enable unbounded dynamic - * allocation using malloc. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC. - * - */ -#ifndef INET_CONFIG_NUM_BUFS -#define INET_CONFIG_NUM_BUFS CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC -#endif // INET_CONFIG_NUM_BUFS - -/** - * @def INET_CONFIG_NUM_TIMERS - * - * @brief - * This is the total number of available timers. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_NUM_TIMERS. - * - */ -#ifndef INET_CONFIG_NUM_TIMERS -#define INET_CONFIG_NUM_TIMERS CHIP_SYSTEM_CONFIG_NUM_TIMERS -#endif // INET_CONFIG_NUM_TIMERS - -/** - * @def INET_CONFIG_HEADER_RESERVE_SIZE - * - * @brief - * The number of bytes to reserve in a network packet buffer to contain - * all the possible protocol encapsulation headers before the application - * message text. - * - * @note - * By default, this parameter is a copy of CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE. - * - */ -#ifndef INET_CONFIG_HEADER_RESERVE_SIZE -#define INET_CONFIG_HEADER_RESERVE_SIZE CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE -#endif // INET_CONFIG_HEADER_RESERVE_SIZE - -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -/** - * @def INET_CONFIG_TEST - * - * @brief - * Defines whether (1) or not (0) to enable testing aids - */ -#ifndef INET_CONFIG_TEST -#define INET_CONFIG_TEST 0 -#endif - -/** - * @def INET_CONFIG_TUNNEL_DEVICE_NAME - * - * @brief - * Defines tunnel device name - */ -#ifndef INET_CONFIG_TUNNEL_DEVICE_NAME -#define INET_CONFIG_TUNNEL_DEVICE_NAME "/dev/net/tun" -#endif //INET_CONFIG_TUNNEL_DEVICE_NAME - -/** - * @def INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - * - * @brief Enable asynchronous dns name resolution for Linux sockets. - */ -#ifndef INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#define INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS 1 -#endif // INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - -/** - * @def INET_CONFIG_DNS_ASYNC_MAX_THREAD_COUNT - * - * @brief The maximum number of POSIX threads that would be performing - * asynchronous DNS resolution. - */ -#ifndef INET_CONFIG_DNS_ASYNC_MAX_THREAD_COUNT -#define INET_CONFIG_DNS_ASYNC_MAX_THREAD_COUNT 2 -#endif // INET_CONFIG_DNS_ASYNC_MAX_THREAD_COUNT - -/** - * @def INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - * - * @brief - * When this flag is set, the InetLayer implements - * a mechanism that simulates the TCP_USER_TIMEOUT - * socket option for Linux sockets. - * - * @details - * The TCP_USER_TIMEOUT option specifies the maximum - * amount of time in milliseconds that transmitted - * data may remain unacknowledged before TCP will - * forcibly close the corresponding connection. - * See RFC 5482, for further details. - * - * This flag is set to override the usage of the system - * defined TCP_USER_TIMEOUT socket option for Linux. - * The reason for having this overriding feature - * was to overcome some limitations of the system - * socket option wherein the TCP_USER_TIMEOUT was - * not taking effect when - * 1) The IP address of the interface of the TCP - * connection was removed. - * 2) The interface of the TCP connection was - * brought down. - * - */ -#ifndef INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT -#define INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT 1 -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - -/** - * @def INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - * - * @brief - * When this flag is set, the InetLayer enables - * callbacks to the upper layer notifying it when - * the send channel of the TCP connection changes - * between being idle or not idle. - * - * @note - * When enabled, the TCP send queue is actively - * polled to determine if sent data has been - * acknowledged. - * - */ -#ifndef INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS -#define INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS 0 -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - -/** - * @def INET_CONFIG_TCP_SEND_QUEUE_POLL_INTERVAL_MSEC - * - * @brief - * The default polling interval to check the progress - * on the TCP SendQueue to determine if sent data is - * being acknowledged. - * - * @details - * If progress is being made, then the TCP UserTimeout - * period would be shifted further ahead by resetting - * the max poll count. If, however, progress is not made, - * then the next timer would still fire at the next poll - * interval without resetting the poll count. The - * connection would be torn down when the poll count - * reaches zero. - */ -#ifndef INET_CONFIG_TCP_SEND_QUEUE_POLL_INTERVAL_MSEC -#define INET_CONFIG_TCP_SEND_QUEUE_POLL_INTERVAL_MSEC 500 -#endif // INET_CONFIG_TCP_SEND_QUEUE_POLL_INTERVAL_MSEC - -/** - * @def INET_CONFIG_DEFAULT_TCP_USER_TIMEOUT_MSEC - * - * @brief - * The default value of the TCP_USER_TIMEOUT in - * milliseconds. Set to equivalent of 5 minutes. - * - * - * @details - * This value specifies the maximum amount of - * time in milliseconds that transmitted data may remain - * unacknowledged before TCP will forcibly close the - * corresponding connection. - * See RFC 5482, for further details. - */ -#ifndef INET_CONFIG_DEFAULT_TCP_USER_TIMEOUT_MSEC -#define INET_CONFIG_DEFAULT_TCP_USER_TIMEOUT_MSEC (5 * 60 * 1000) -#endif // INET_CONFIG_DEFAULT_TCP_USER_TIMEOUT_MSEC - -/** - * @def INET_CONFIG_IP_MULTICAST_HOP_LIMIT - * - * @brief - * The default value of the Hop Limit field in - * the IP multicast packet. - * - * - * @details - * This value specifies the hop limit that could be set in the - * outgoing IP packet to override any default settings(made by - * the kernel) for the hop limit field in the IP header. - * On Linux platforms, the hoplimit field is set to 1 for - * multicast packets. - */ -#ifndef INET_CONFIG_IP_MULTICAST_HOP_LIMIT -#define INET_CONFIG_IP_MULTICAST_HOP_LIMIT (64) -#endif // INET_CONFIG_IP_MULTICAST_HOP_LIMIT -// clang-format on - -#endif /* INETCONFIG_H */ diff --git a/src/inet/InetError.cpp b/src/inet/InetError.cpp deleted file mode 100644 index a21856d5c52195..00000000000000 --- a/src/inet/InetError.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * - * - * 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 contains functions for working with Inet Layer errors. - */ - -#include - -#include -#include - -#include - - -extern void FormatError(char * buf, uint16_t bufSize, const char * subsys, int32_t err, const char * desc); - -namespace chip { -namespace Inet { - -/** - * Register a text error formatter for Inet Layer errors. - */ -void RegisterInetLayerErrorFormatter(void) -{ - static chip::ErrorFormatter sInetLayerErrorFormatter = - { - FormatInetLayerError, - NULL - }; - - RegisterErrorFormatter(&sInetLayerErrorFormatter); -} - -/** - * Given an Inet Layer error, returns a human-readable NULL-terminated C string - * describing the error. - * - * @param[in] buf Buffer into which the error string will be placed. - * @param[in] bufSize Size of the supplied buffer in bytes. - * @param[in] err The error to be described. - * - * @return true If a description string was written into the supplied buffer. - * @return false If the supplied error was not an Inet Layer error. - * - */ -bool FormatInetLayerError(char * buf, uint16_t bufSize, int32_t err) -{ - const char * desc = NULL; - - if (err < INET_ERROR_MIN || err > INET_ERROR_MAX) - { - return false; - } - -#if !CHIP_CONFIG_SHORT_ERROR_STR - switch (err) - { - case INET_ERROR_WRONG_ADDRESS_TYPE : desc = "Wrong address type"; break; - case INET_ERROR_CONNECTION_ABORTED : desc = "TCP connection aborted"; break; - case INET_ERROR_PEER_DISCONNECTED : desc = "Peer disconnected"; break; - case INET_ERROR_INCORRECT_STATE : desc = "Incorrect state"; break; - case INET_ERROR_MESSAGE_TOO_LONG : desc = "Message too long"; break; - case INET_ERROR_NO_CONNECTION_HANDLER : desc = "No TCP connection handler"; break; - case INET_ERROR_NO_MEMORY : desc = "No memory"; break; - case INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED : desc = "Outbound message truncated"; break; - case INET_ERROR_INBOUND_MESSAGE_TOO_BIG : desc = "Inbound message too big"; break; - case INET_ERROR_HOST_NOT_FOUND : desc = "Host not found"; break; - case INET_ERROR_DNS_TRY_AGAIN : desc = "DNS try again"; break; - case INET_ERROR_DNS_NO_RECOVERY : desc = "DNS no recovery"; break; - case INET_ERROR_BAD_ARGS : desc = "Bad arguments"; break; - case INET_ERROR_WRONG_PROTOCOL_TYPE : desc = "Wrong protocol type"; break; - case INET_ERROR_UNKNOWN_INTERFACE : desc = "Unknown interface"; break; - case INET_ERROR_NOT_IMPLEMENTED : desc = "Not implemented"; break; - case INET_ERROR_ADDRESS_NOT_FOUND : desc = "Address not found"; break; - case INET_ERROR_HOST_NAME_TOO_LONG : desc = "Host name too long"; break; - case INET_ERROR_INVALID_HOST_NAME : desc = "Invalid host name"; break; - case INET_ERROR_NOT_SUPPORTED : desc = "Not supported"; break; - case INET_ERROR_NO_ENDPOINTS : desc = "No more TCP endpoints"; break; - case INET_ERROR_IDLE_TIMEOUT : desc = "Idle timeout"; break; - case INET_ERROR_UNEXPECTED_EVENT : desc = "Unexpected event"; break; - case INET_ERROR_INVALID_IPV6_PKT : desc = "Invalid IPv6 Packet"; break; - case INET_ERROR_INTERFACE_INIT_FAILURE : desc = "Failure to initialize interface"; break; - case INET_ERROR_TCP_USER_TIMEOUT : desc = "TCP User Timeout"; break; - case INET_ERROR_TCP_CONNECT_TIMEOUT : desc = "TCP Connect Timeout"; break; - case INET_ERROR_INCOMPATIBLE_IP_ADDRESS_TYPE : desc = "Incompatible IP address type"; break; - } -#endif // !CHIP_CONFIG_SHORT_ERROR_STR - - FormatError(buf, bufSize, "Inet", err, desc); - - return true; -} - -} // namespace Inet -} // namespace chip diff --git a/src/inet/InetError.h b/src/inet/InetError.h deleted file mode 100644 index a6e1a1b78433be..00000000000000 --- a/src/inet/InetError.h +++ /dev/null @@ -1,517 +0,0 @@ -/* - * - * - * - * 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 constants for the Nest InetLayer subsystem. - * - * Error types, ranges, and mappings overrides may be made by - * defining the appropriate INET_CONFIG_* or _INET_CONFIG_* - * macros. - * - * NOTE WELL: On some platforms, this header is included by C-language programs. - * - */ - -#ifndef INETERROR_H -#define INETERROR_H - -#include - -#include - -// clang-format off - -/** - * The basic type for all InetLayer errors. - * - * This is defined to a platform- or system-specific type. - * - */ -typedef INET_CONFIG_ERROR_TYPE INET_ERROR; - -/** - * @def INET_ERROR_MIN - * - * @brief - * This defines the base or minimum InetLayer error number - * range. This value may be configured via #INET_CONFIG_ERROR_MIN. - * - */ -#define INET_ERROR_MIN INET_CONFIG_ERROR_MIN - -/** - * @def INET_ERROR_MAX - * - * @brief - * This defines the top or maximum InetLayer error number - * range. This value may be configured via #INET_CONFIG_ERROR_MAX. - * - */ -#define INET_ERROR_MAX INET_CONFIG_ERROR_MAX - -/** - * @def _INET_ERROR(e) - * - * @brief - * This defines a mapping function for InetLayer errors that allows - * mapping such errors into a platform- or system-specific - * range. This function may be configured via - * #_INET_CONFIG_ERROR(e). - * - * @param[in] e The InetLayer error to map. - * - * @return The mapped InetLayer error. - * - */ -#define _INET_ERROR(e) _INET_CONFIG_ERROR(e) - -/** - * @def INET_NO_ERROR - * - * @brief - * This defines the InetLayer error code for success or no - * error. This value may be configured via #INET_CONFIG_NO_ERROR. - * - */ -#define INET_NO_ERROR INET_CONFIG_NO_ERROR - -/** - * @name Error Definitions - * - * @{ - */ - -/** - * @def INET_ERROR_WRONG_ADDRESS_TYPE - * - * @brief - * The Internet Protocol (IP) address type or scope does not match - * the expected type or scope. - * - */ -#define INET_ERROR_WRONG_ADDRESS_TYPE _INET_ERROR(0) - -/** - * @def INET_ERROR_CONNECTION_ABORTED - * - * @brief - * A connection has been aborted. - * - */ -#define INET_ERROR_CONNECTION_ABORTED _INET_ERROR(1) - -/** - * @def INET_ERROR_PEER_DISCONNECTED - * - * @brief - * A remote connection peer disconnected. - * - */ -#define INET_ERROR_PEER_DISCONNECTED _INET_ERROR(2) - -/** - * @def INET_ERROR_INCORRECT_STATE - * - * @brief - * An unexpected state was encountered. - * - */ -#define INET_ERROR_INCORRECT_STATE _INET_ERROR(3) - -/** - * @def INET_ERROR_MESSAGE_TOO_LONG - * - * @brief - * A message is too long. - * - */ -#define INET_ERROR_MESSAGE_TOO_LONG _INET_ERROR(4) - -/** - * @def INET_ERROR_NO_CONNECTION_HANDLER - * - * @brief - * No callback has been registered for handling an incoming TCP - * connection. - * - */ -#define INET_ERROR_NO_CONNECTION_HANDLER _INET_ERROR(5) - -/** - * @def INET_ERROR_NO_MEMORY - * - * @brief - * A request for memory could not be fulfilled. - * - */ -#define INET_ERROR_NO_MEMORY _INET_ERROR(6) - -/** - * @def INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED - * - * @brief - * Fewer message bytes were sent than requested. - * - */ -#define INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED _INET_ERROR(7) - -/** - * @def INET_ERROR_INBOUND_MESSAGE_TOO_BIG - * - * @brief - * More message data is pending than available buffer space - * available to copy it. - * - */ -#define INET_ERROR_INBOUND_MESSAGE_TOO_BIG _INET_ERROR(8) - -/** - * @def INET_ERROR_HOST_NOT_FOUND - * - * @brief - * A requested host name could not be resolved to an address. - * - */ -#define INET_ERROR_HOST_NOT_FOUND _INET_ERROR(9) - -/** - * @def INET_ERROR_DNS_TRY_AGAIN - * - * @brief - * A name server returned a temporary failure indication; try - * again later. - * - */ -#define INET_ERROR_DNS_TRY_AGAIN _INET_ERROR(10) - -/** - * @def INET_ERROR_DNS_NO_RECOVERY - * - * @brief - * A name server returned an unrecoverable error. - * - */ -#define INET_ERROR_DNS_NO_RECOVERY _INET_ERROR(11) - -/** - * @def INET_ERROR_BAD_ARGS - * - * @brief - * An invalid argument or arguments were supplied. - * - */ -#define INET_ERROR_BAD_ARGS _INET_ERROR(12) - -/** - * @def INET_ERROR_WRONG_PROTOCOL_TYPE - * - * @brief - * An incorrect or unexpected protocol type was encountered. - * - */ -#define INET_ERROR_WRONG_PROTOCOL_TYPE _INET_ERROR(13) - -/** - * @def INET_ERROR_UNKNOWN_INTERFACE - * - * @brief - * An unknown interface identifier was encountered. - * - */ -#define INET_ERROR_UNKNOWN_INTERFACE _INET_ERROR(14) - -/** - * @def INET_ERROR_NOT_IMPLEMENTED - * - * @brief - * A requested function or feature is not implemented. - * - */ -#define INET_ERROR_NOT_IMPLEMENTED _INET_ERROR(15) - -/** - * @def INET_ERROR_ADDRESS_NOT_FOUND - * - * @brief - * A requested address type, class, or scope cannot be found. - * - */ -#define INET_ERROR_ADDRESS_NOT_FOUND _INET_ERROR(16) - -/** - * @def INET_ERROR_HOST_NAME_TOO_LONG - * - * @brief - * A requested host name is too long. - * - */ -#define INET_ERROR_HOST_NAME_TOO_LONG _INET_ERROR(17) - -/** - * @def INET_ERROR_INVALID_HOST_NAME - * - * @brief - * A requested host name and port is invalid. - * - */ -#define INET_ERROR_INVALID_HOST_NAME _INET_ERROR(18) - -/** - * @def INET_ERROR_NOT_SUPPORTED - * - * @brief - * A requested function or feature is not supported. - * - */ -#define INET_ERROR_NOT_SUPPORTED _INET_ERROR(19) - -/** - * @def INET_ERROR_NO_ENDPOINTS - * - * @brief - * No endpoint of the specified type is available. - * - */ -#define INET_ERROR_NO_ENDPOINTS _INET_ERROR(20) - -/** - * @def INET_ERROR_IDLE_TIMEOUT - * - * @brief - * A TCP connection timed out due to inactivity. - * - */ -#define INET_ERROR_IDLE_TIMEOUT _INET_ERROR(21) - -/** - * @def INET_ERROR_UNEXPECTED_EVENT - * - * @brief - * An unexpected event occurred or was handled. - * - */ -#define INET_ERROR_UNEXPECTED_EVENT _INET_ERROR(22) - -/** - * @def INET_ERROR_INVALID_IPV6_PKT - * - * @brief - * An IPv6 packet is invalid. - * - */ -#define INET_ERROR_INVALID_IPV6_PKT _INET_ERROR(23) - -/** - * @def INET_ERROR_INTERFACE_INIT_FAILURE - * - * @brief - * Failure to initialize an interface. - * - */ -#define INET_ERROR_INTERFACE_INIT_FAILURE _INET_ERROR(24) - -/** - * @def INET_ERROR_TCP_USER_TIMEOUT - * - * @brief - * TCP Connection timed out waiting for - * acknowledgment for transmitted packet. - * - */ -#define INET_ERROR_TCP_USER_TIMEOUT _INET_ERROR(25) - -/** - * @def INET_ERROR_TCP_CONNECT_TIMEOUT - * - * @brief - * TCP Connection timed out waiting for - * a successful connection or a report - * of an error. - * - */ -#define INET_ERROR_TCP_CONNECT_TIMEOUT _INET_ERROR(26) - -/** - * @def INET_ERROR_INCOMPATIBLE_IP_ADDRESS_TYPE - * - * @brief - * The supplied text-form IP address was not compatible with the requested - * IP address type. - * - */ -#define INET_ERROR_INCOMPATIBLE_IP_ADDRESS_TYPE _INET_ERROR(27) - -// !!!!! IMPORTANT !!!!! -// -// If you add new Inet errors, please update the translation of error -// codes to strings in InetError.cpp, and add them to unittest -// in test-apps/TestErrorStr.cpp - -/** - * @} - */ - -// clang-format on - -namespace chip { -namespace Inet { - -extern void RegisterInetLayerErrorFormatter(void); -extern bool FormatInetLayerError(char * buf, uint16_t bufSize, int32_t err); - -} // namespace Inet -} // namespace chip - - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -/** - * @name Error Mapping and Description Functions - * - * @{ - */ - -#if INET_CONFIG_WILL_OVERRIDE_OS_ERROR_FUNCS - -extern INET_ERROR INET_MapOSError(int e); -extern const char *INET_DescribeOSError(INET_ERROR err); -extern bool INET_IsOSError(INET_ERROR err); - -#else // !INET_CONFIG_WILL_OVERRIDE_OS_ERROR_FUNCS - -#ifdef __cplusplus - -/** - * This implements a mapping function for InetLayer errors that allows - * mapping underlying POSIX network and OS stack errors into a - * platform- or system-specific range. - * - * @param[in] e The POSIX network or OS error to map. - * - * @return The mapped POSIX network or OS error. - * - */ -static inline INET_ERROR INET_MapOSError(int e) -{ - return static_cast(::chip::System::MapErrorPOSIX(e)); -} - -/** - * This implements a function to return an NULL-terminated OS-specific - * descriptive C string, associated with the specified, mapped OS - * error. - * - * @param[in] err The mapped OS-specific error to describe. - * - * @return A NULL-terminated, OS-specific descriptive C string - * describing the error. - * - */ -static inline const char *INET_DescribeOSError(INET_ERROR err) -{ - return ::chip::System::DescribeErrorPOSIX(err); -} - -/** - * This implements an introspection function for InetLayer errors that - * allows the caller to determine whether the specified error is an - * internal, underlying OS error. - * - * @param[in] err The mapped error to determine whether it is an OS - * error. - * - * @return True if the specified error is an OS error; otherwise, false. - * - */ -static inline bool INET_IsOSError(INET_ERROR err) -{ - return ::chip::System::IsErrorPOSIX(err); -} - -#endif // !defined(__cplusplus) -#endif // !INET_CONFIG_WILL_OVERRIDE_OS_ERROR_FUNCS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if INET_CONFIG_WILL_OVERRIDE_LWIP_ERROR_FUNCS - -extern INET_ERROR INET_MapLwIPError(err_t e); -extern const char *INET_DescribeLwIPError(INET_ERROR err); -extern bool INET_IsLwIPError(INET_ERROR err); - -#else // !INET_CONFIG_WILL_OVERRIDE_LWIP_ERROR_FUNCS - -#ifdef __cplusplus - -/** - * This implements a mapping function for InetLayer errors that allows - * mapping underlying LwIP network stack errors into a platform- or - * system-specific range. - * - * @param[in] e The LwIP error to map. - * - * @return The mapped LwIP network or OS error. - * - */ -static inline INET_ERROR INET_MapLwIPError(err_t e) -{ - return static_cast(::chip::System::MapErrorLwIP(e)); -} - -/** - * This implements a function to return an NULL-terminated - * LwIP-specific descriptive C string, associated with the specified, - * mapped LwIP error. - * - * @param[in] err The mapped LwIP-specific error to describe. - * - * @return A NULL-terminated, LwIP-specific descriptive C string - * describing the error. - * - */ -static inline const char *INET_DescribeLwIPError(INET_ERROR err) -{ - return ::chip::System::DescribeErrorLwIP(err); -} - -/** - * This implements an introspection function for InetLayer errors that - * allows the caller to determine whether the specified error is an - * internal, underlying LwIP error. - * - * @param[in] err The mapped error to determine whether it is a LwIP - * error. - * - * @return True if the specified error is a LwIP error; otherwise, false. - * - */ -static inline bool INET_IsLwIPError(INET_ERROR err) -{ - return ::chip::System::IsErrorLwIP(err); -} - -#endif // !defined(__cplusplus) -#endif // !INET_CONFIG_WILL_OVERRIDE_LWIP_ERROR_FUNCS -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -/** - * @} - */ - -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -#endif // !defined(INETERROR_H) diff --git a/src/inet/InetFaultInjection.cpp b/src/inet/InetFaultInjection.cpp deleted file mode 100644 index 06cbf883ec2a7f..00000000000000 --- a/src/inet/InetFaultInjection.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * - * - * 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 - * Implementation of the fault-injection utilities for Inet. - */ - -#include -#include "InetFaultInjection.h" - -#if INET_CONFIG_TEST - - -namespace chip { -namespace Inet { -namespace FaultInjection { - -static FaultInjection::Record sFaultRecordArray[kFault_NumItems]; -static class FaultInjection::Manager sInetFaultInMgr; -static const FaultInjection::Name sManagerName = "Inet"; -static const FaultInjection::Name sFaultNames[] = { - "DNSResolverNew", - "Send", - "SendNonCritical", -}; - - -/** - * Get the singleton FaultInjection::Manager for Inet faults - */ -FaultInjection::Manager &GetManager(void) -{ - if (0 == sInetFaultInMgr.GetNumFaults()) - { - sInetFaultInMgr.Init(kFault_NumItems, - sFaultRecordArray, - sManagerName, - sFaultNames); - } - return sInetFaultInMgr; -} - -} // namespace FaultInjection -} // namespace Inet -} // namespace chip - -#endif // INET_CONFIG_TEST diff --git a/src/inet/InetFaultInjection.h b/src/inet/InetFaultInjection.h deleted file mode 100644 index 07a3fa3bc80a50..00000000000000 --- a/src/inet/InetFaultInjection.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * - * - * 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 - * Header file for the fault-injection utilities for Inet. - */ - -#ifndef INET_FAULT_INJECTION_H_ -#define INET_FAULT_INJECTION_H_ - -#include - -#if INET_CONFIG_TEST - -#include - -#include - -#include - -namespace chip { -namespace Inet { -namespace FaultInjection { - -/** - * @brief Fault injection points - * - * @details - * Each point in the code at which a fault can be injected - * is identified by a member of this enum. - */ -typedef enum -{ - kFault_DNSResolverNew, /**< Fail the allocation of a DNSResolver object */ - kFault_Send, /**< Fail sending a message over TCP or UDP */ - kFault_SendNonCritical, /**< Fail sending a UDP message returning an error considered non-critical by WRMP */ - kFault_NumItems, -} InetFaultInjectionID; - -DLL_EXPORT FaultInjection::Manager &GetManager(void); - -} // namespace FaultInjection -} // namespace Inet -} // namespace chip - -/** - * Execute the statements included if the Inet fault is - * to be injected. - * - * @param[in] aFaultID An Inet fault-injection id - * @param[in] aStatements Statements to be executed if the fault is enabled. - */ -#define INET_FAULT_INJECT( aFaultID, aStatement ) \ - nlFAULT_INJECT(Inet::FaultInjection::GetManager(), aFaultID, aStatement) - -#else // INET_CONFIG_TEST - -#define INET_FAULT_INJECT( aFaultID, aStatement ) - -#endif // INET_CONFIG_TEST - - -#endif // INET_FAULT_INJECTION_H_ diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp deleted file mode 100644 index f0e41a40a7b298..00000000000000 --- a/src/inet/InetInterface.cpp +++ /dev/null @@ -1,922 +0,0 @@ -/* - * - * - * - * 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 - * Implementation of network interface abstraction layer. - * - */ - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif - -#include -#include - -#include -#include - -#include -#include -#include "IPPrefix.h" - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include -#include -#include -#include -#ifdef HAVE_SYS_SOCKIO_H -#include -#endif /* HAVE_SYS_SOCKIO_H */ -#include -#include -#ifdef __ANDROID__ -#include "ifaddrs-android.h" -#else // !defined(__ANDROID__) -#include -#endif // !defined(__ANDROID__) -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -namespace chip { -namespace Inet { - - -/** - * @brief Get the name of a network interface - * - * @param[in] intfId a network interface - * @param[in] nameBuf region of memory to write the interface name - * @param[in] nameBufSize size of the region denoted by \c nameBuf - * - * @retval INET_NO_ERROR successful result, interface name written - * @retval INET_ERROR_NO_MEMORY name is too large to be written in buffer - * @retval other another system or platform error - * - * @details - * Writes the name of the network interface as \c NUL terminated text string - * at \c nameBuf. The name of the unspecified network interface is the empty - * string. - */ -DLL_EXPORT INET_ERROR GetInterfaceName(InterfaceId intfId, char *nameBuf, size_t nameBufSize) -{ - if (intfId != INET_NULL_INTERFACEID) - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP - int status = snprintf(nameBuf, nameBufSize, "%c%c%d", intfId->name[0], intfId->name[1], intfId->num); - if (status >= static_cast(nameBufSize)) - return INET_ERROR_NO_MEMORY; - return INET_NO_ERROR; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - char intfName[IF_NAMESIZE]; - if (if_indextoname(intfId, intfName) == NULL) - return chip::System::MapErrorPOSIX(errno); - if (strlen(intfName) >= nameBufSize) - return INET_ERROR_NO_MEMORY; - strcpy(nameBuf, intfName); - return INET_NO_ERROR; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - } - else - { - if (nameBufSize < 1) - return INET_ERROR_NO_MEMORY; - nameBuf[0] = 0; - return INET_NO_ERROR; - } -} - -/** - * @brief Search the list of network interfaces for the indicated name. - * - * @param[in] intfName name of the network interface to find - * @param[out] intfId indicator of the network interface to assign - * - * @retval INET_NO_ERROR success, network interface indicated - * @retval INET_ERROR_UNKNOWN_INTERFACE no network interface found - * @retval other another system or platform error - * - * @details - * On LwIP, this function must be called with the LwIP stack lock acquired. - * - * The \c intfId parameter is not updated unless the value returned is - * \c INET_NO_ERROR. It should be initialized with \c INET_NULL_INTERFACEID - * before calling this function. - */ -DLL_EXPORT INET_ERROR InterfaceNameToId(const char *intfName, InterfaceId& intfId) -{ -#if CHIP_SYSTEM_CONFIG_USE_LWIP - if (strlen(intfName) < 3) - return INET_ERROR_UNKNOWN_INTERFACE; - char *parseEnd; - unsigned long intfNum = strtoul(intfName + 2, &parseEnd, 10); - if (*parseEnd != 0 || intfNum > UINT8_MAX) - return INET_ERROR_UNKNOWN_INTERFACE; - struct netif * intf; -#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 0 && defined(NETIF_FOREACH) - NETIF_FOREACH(intf) -#else - for (intf = netif_list; intf != NULL; intf = intf->next) -#endif - { - if (intf->name[0] == intfName[0] && intf->name[1] == intfName[1] && intf->num == (uint8_t)intfNum) - { - intfId = intf; - return INET_NO_ERROR; - } - } - intfId = INET_NULL_INTERFACEID; - return INET_ERROR_UNKNOWN_INTERFACE; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - intfId = if_nametoindex(intfName); - if (intfId == 0) - return (errno == ENXIO) ? INET_ERROR_UNKNOWN_INTERFACE : chip::System::MapErrorPOSIX(errno); - return INET_NO_ERROR; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -} - - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -static int sIOCTLSocket = -1; - -/** - * @brief Returns a global general purpose socket useful for invoking certain network IOCTLs. - * - * This function is thread-safe on all platforms. - */ -int GetIOCTLSocket(void) -{ - if (sIOCTLSocket == -1) - { - int s; -#ifdef SOCK_CLOEXEC - s = socket(AF_INET, SOCK_STREAM, SOCK_CLOEXEC); - if (s < 0) -#endif - { - s = socket(AF_INET, SOCK_STREAM, 0); - fcntl(s, O_CLOEXEC); - } - - if (!__sync_bool_compare_and_swap(&sIOCTLSocket, -1, s)) - { - close(s); - } - } - return sIOCTLSocket; -} - -/** - * @brief Close the global socket created by \c GetIOCTLSocket. - * - * @details - * This function is provided for cases were leaving the global IOCTL socket - * open would register as a leak. - * - * NB: This function is NOT thread-safe with respect to \c GetIOCTLSocket. - */ -void CloseIOCTLSocket(void) -{ - if (sIOCTLSocket == -1) - { - close(sIOCTLSocket); - sIOCTLSocket = -1; - } -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - -/** - * @fn InterfaceIterator::InterfaceIterator(void) - * - * @brief Constructs an InterfaceIterator object. - * - * @details - * Starts the iterator at the first network interface. On some platforms, - * this constructor may allocate resources recycled by the destructor. - */ - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -InterfaceIterator::InterfaceIterator(void) -{ - mIntfArray = NULL; - mCurIntf = 0; - mIntfFlags = 0; - mIntfFlagsCached = 0; -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/** - * @fn InterfaceIterator::~InterfaceIterator(void) - * - * @brief Destroys an InterfaceIterator object. - * - * @details - * Recycles any resources allocated by the constructor. - */ - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -InterfaceIterator::~InterfaceIterator(void) -{ - if (mIntfArray != NULL) - { - if_freenameindex(mIntfArray); - mIntfArray = NULL; - } -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/** - * @fn bool InterfaceIterator::HasCurrent(void) - * - * @brief Test whether the iterator is positioned on an interface - * - * @return \c true if the iterator is positioned on an interface; - * \c false if positioned beyond the end of the interface list. - */ - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -bool InterfaceIterator::HasCurrent(void) -{ - return (mIntfArray != NULL) - ? mIntfArray[mCurIntf].if_index != 0 - : Next(); -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/** - * @fn bool InterfaceIterator::Next(void) - * - * @brief Advance the iterator to the next network interface. - * - * @return \c false if advanced beyond the end, else \c true. - * - * @details - * Advances the internal iterator to the next network interface or to a position - * beyond the end of the interface list. - * - * On multi-threaded LwIP systems, this method is thread-safe relative to other - * threads accessing the global LwIP state provided that: 1) the other threads - * hold the LwIP core lock while mutating the list of netifs; and 2) netif objects - * themselves are never destroyed. - * - * Iteration is stable in the face of changes to the underlying system's - * interfaces, *except* in the case of LwIP systems when the currently selected - * interface is removed from the list, which causes iteration to end immediately. - */ -bool InterfaceIterator::Next(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (mIntfArray == NULL) - { - mIntfArray = if_nameindex(); - } - else if (mIntfArray[mCurIntf].if_index != 0) - { - mCurIntf++; - mIntfFlags = 0; - mIntfFlagsCached = false; - } - return (mIntfArray != NULL && mIntfArray[mCurIntf].if_index != 0); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Verify the previous netif is still on the list if netifs. If so, - // advance to the next nextif. - struct netif * prevNetif = mCurNetif; -#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 0 && defined(NETIF_FOREACH) - NETIF_FOREACH(mCurNetif) -#else - for (mCurNetif = netif_list; mCurNetif != NULL; mCurNetif = mCurNetif->next) -#endif - { - if (mCurNetif == prevNetif) - { - mCurNetif = mCurNetif->next; - break; - } - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - return mCurNetif != NULL; - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -} - -/** - * @fn InterfaceId InterfaceIterator::GetInterfaceId(void) - * - * @brief Returns the network interface id at the current iterator position. - * - * @retval INET_NULL_INTERFACEID if advanced beyond the end of the list. - * @retval id the current network interface id. - */ - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -InterfaceId InterfaceIterator::GetInterfaceId(void) -{ - return (HasCurrent()) - ? mIntfArray[mCurIntf].if_index - : INET_NULL_INTERFACEID; -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - -/** - * @brief Get the name of the current network interface - * - * @param[in] nameBuf region of memory to write the interface name - * @param[in] nameBufSize size of the region denoted by \c nameBuf - * - * @retval INET_NO_ERROR successful result, interface name written - * @retval INET_ERROR_INCORRECT_STATE - * iterator is positioned beyond the end of - * the list - * @retval INET_ERROR_NO_MEMORY name is too large to be written in buffer - * @retval other another system or platform error - * - * @details - * Writes the name of the network interface as \c NUL terminated text string - * at \c nameBuf. - */ -INET_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) -{ - INET_ERROR err = INET_ERROR_NOT_IMPLEMENTED; - - VerifyOrExit(HasCurrent(), err = INET_ERROR_INCORRECT_STATE); - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - VerifyOrExit(strlen(mIntfArray[mCurIntf].if_name) < nameBufSize, err = INET_ERROR_NO_MEMORY); - strncpy(nameBuf, mIntfArray[mCurIntf].if_name, nameBufSize); - err = INET_NO_ERROR; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - err = ::Inet::GetInterfaceName(mCurNetif, nameBuf, nameBufSize); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -exit: - return err; -} - -/** - * @brief Returns whether the current network interface is up. - * - * @return \c true if current network interface is up, \c false if not - * or if the iterator is positioned beyond the end of the list. - */ -bool InterfaceIterator::IsUp(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return (GetFlags() & IFF_UP) != 0; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - return HasCurrent() && netif_is_up(mCurNetif); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -} - -/** - * @brief Returns whether the current network interface supports multicast. - * - * @return \c true if current network interface supports multicast, \c false - * if not, or if the iterator is positioned beyond the end of the list. - */ -bool InterfaceIterator::SupportsMulticast(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return (GetFlags() & IFF_MULTICAST) != 0; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - return HasCurrent() && -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - (mCurNetif->flags & (NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_BROADCAST)) != 0; -#else - (mCurNetif->flags & NETIF_FLAG_POINTTOPOINT) == 0; -#endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -} - -/** - * @brief Returns whether the current network interface has a broadcast address. - * - * @return \c true if current network interface has a broadcast address, \c false - * if not, or if the iterator is positioned beyond the end of the list. - */ -bool InterfaceIterator::HasBroadcastAddress(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return (GetFlags() & IFF_BROADCAST) != 0; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - return HasCurrent() && (mCurNetif->flags & NETIF_FLAG_BROADCAST) != 0; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -} - -/** - * @fn short InterfaceIterator::GetFlags(void) - * - * @brief Returns the ifr_flags value for the current interface. - */ - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -short InterfaceIterator::GetFlags(void) -{ - struct ifreq intfData; - - if (!mIntfFlagsCached && HasCurrent()) - { - strncpy(intfData.ifr_name, mIntfArray[mCurIntf].if_name, IFNAMSIZ); - intfData.ifr_name[IFNAMSIZ-1] = '\0'; - - int res = ioctl(GetIOCTLSocket(), SIOCGIFFLAGS, &intfData); - if (res == 0) - { - mIntfFlags = intfData.ifr_flags; - mIntfFlagsCached = true; - } - } - - return mIntfFlags; -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/** - * @fn InterfaceAddressIterator::InterfaceAddressIterator(void) - * - * @brief Constructs an InterfaceAddressIterator object. - * - * @details - * Starts the iterator at the first network address. On some platforms, - * this constructor may allocate resources recycled by the destructor. - */ - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -InterfaceAddressIterator::InterfaceAddressIterator(void) -{ - mAddrsList = NULL; - mCurAddr = NULL; -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - -/** - * @fn InterfaceAddressIterator::~InterfaceAddressIterator(void) - * - * @brief Destroys an InterfaceAddressIterator object. - * - * @details - * Recycles any resources allocated by the constructor. - */ - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -InterfaceAddressIterator::~InterfaceAddressIterator(void) -{ - if (mAddrsList != NULL) - { - freeifaddrs(mAddrsList); - mAddrsList = mCurAddr = NULL; - } -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/** - * @fn bool InterfaceIterator::HasCurrent(void) - * - * @brief Test whether the iterator is positioned on an interface address - * - * @return \c true if the iterator is positioned on an interface address; - * \c false if positioned beyond the end of the address list. - */ -bool InterfaceAddressIterator::HasCurrent(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return (mAddrsList != NULL) ? (mCurAddr != NULL) : Next(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - return mIntfIter.HasCurrent() && ((mCurAddrIndex != kBeforeStartIndex) || Next()); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -} - -/** - * @fn bool InterfaceAddressIterator::Next(void) - * - * @brief Advance the iterator to the next interface address. - * - * @return \c false if advanced beyond the end, else \c true. - * - * @details - * Advances the iterator to the next interface address or to a position - * beyond the end of the address list. - * - * On LwIP, this method is thread-safe provided that: 1) other threads hold - * the LwIP core lock while mutating the netif list; and 2) netif objects - * themselves are never destroyed. Additionally, iteration on LwIP systems - * will terminate early if the current interface is removed from the list. - */ -bool InterfaceAddressIterator::Next(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - while (true) - { - if (mAddrsList == NULL) - { - int res = getifaddrs(&mAddrsList); - if (res < 0) - { - return false; - } - mCurAddr = mAddrsList; - } - else if (mCurAddr != NULL) - { - mCurAddr = mCurAddr->ifa_next; - } - - if (mCurAddr == NULL) - { - return false; - } - - if (mCurAddr->ifa_addr != NULL && - (mCurAddr->ifa_addr->sa_family == AF_INET6 -#if INET_CONFIG_ENABLE_IPV4 - || mCurAddr->ifa_addr->sa_family == AF_INET -#endif // INET_CONFIG_ENABLE_IPV4 - )) - { - return true; - } - } - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - mCurAddrIndex++; - - while (mIntfIter.HasCurrent()) - { - struct netif * curIntf = mIntfIter.GetInterfaceId(); - - while (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES) - { - if (ip6_addr_isvalid(netif_ip6_addr_state(curIntf, mCurAddrIndex))) - { - return true; - } - mCurAddrIndex++; - } - -#if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - if (mCurAddrIndex == LWIP_IPV6_NUM_ADDRESSES) - { - if (!ip4_addr_isany(netif_ip4_addr(curIntf))) - { - return true; - } - } -#endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - - mIntfIter.Next(); - mCurAddrIndex = 0; - } - - return false; - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -} - -/** - * @fn IPAddress InterfaceAddressIterator::GetAddress(void) - * - * @brief Get the current interface address. - * - * @return the current interface address or \c IPAddress::Any if the iterator - * is positioned beyond the end of the address list. - */ -IPAddress InterfaceAddressIterator::GetAddress(void) -{ - if (HasCurrent()) - { -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return IPAddress::FromSockAddr(*mCurAddr->ifa_addr); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - struct netif * curIntf = mIntfIter.GetInterfaceId(); - - if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES) - { - return IPAddress::FromIPv6(*netif_ip6_addr(curIntf, mCurAddrIndex)); - } -#if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - else - { - return IPAddress::FromIPv4(*netif_ip4_addr(curIntf)); - } -#endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - } - - return IPAddress::Any; -} - -/** - * @fn uint8_t InterfaceAddressIterator::GetPrefixLength(void) - * - * @brief Gets the network prefix associated with the current interface address. - * - * @return the network prefix (in bits) or 0 if the iterator is positioned beyond - * the end of the address list. - * - * @details - * On LwIP, this method simply returns the hard-coded constant 64. - * - * Note Well: the standard subnet prefix on all links other than PPP - * links is 64 bits. On PPP links and some non-broadcast multipoint access - * links, the convention is either 127 bits or 128 bits, but it might be - * something else. On most platforms, the system's interface address - * structure can represent arbitrary prefix lengths between 0 and 128. - */ -uint8_t InterfaceAddressIterator::GetPrefixLength(void) -{ - if (HasCurrent()) - { -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - if (mCurAddr->ifa_addr->sa_family == AF_INET6) - { - struct sockaddr_in6& netmask = *(struct sockaddr_in6 *)(mCurAddr->ifa_netmask); - return NetmaskToPrefixLength(netmask.sin6_addr.s6_addr, 16); - } - if (mCurAddr->ifa_addr->sa_family == AF_INET) - { - struct sockaddr_in& netmask = *(struct sockaddr_in *)(mCurAddr->ifa_netmask); - return NetmaskToPrefixLength((const uint8_t *)&netmask.sin_addr.s_addr, 4); - } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES) - { - return 64; - } -#if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - else - { - struct netif * curIntf = mIntfIter.GetInterfaceId(); - return NetmaskToPrefixLength((const uint8_t *)netif_ip4_netmask(curIntf), 4); - } -#endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - } - return 0; -} - -/** - * @fn InterfaceId InterfaceAddressIterator::GetInterfaceId(void) - * - * @brief Returns the network interface id associated with the current - * interface address. - * - * @return the interface id or \c INET_NULL_INTERFACEID if the iterator - * is positioned beyond the end of the address list. - */ -InterfaceId InterfaceAddressIterator::GetInterfaceId(void) -{ - if (HasCurrent()) - { -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return if_nametoindex(mCurAddr->ifa_name); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - return mIntfIter.GetInterfaceId(); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - } - return INET_NULL_INTERFACEID; -} - -/** - * @fn INET_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) - * - * @brief Get the name of the network interface associated with the - * current interface address. - * - * @param[in] nameBuf region of memory to write the interface name - * @param[in] nameBufSize size of the region denoted by \c nameBuf - * - * @retval INET_NO_ERROR successful result, interface name written - * @retval INET_ERROR_NO_MEMORY name is too large to be written in buffer - * @retval INET_ERROR_INCORRECT_STATE - * the iterator is not currently positioned on an - * interface address - * @retval other another system or platform error - * - * @details - * Writes the name of the network interface as \c NUL terminated text string - * at \c nameBuf. - */ -INET_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) -{ - INET_ERROR err = INET_ERROR_NOT_IMPLEMENTED; - - VerifyOrExit(HasCurrent(), err = INET_ERROR_INCORRECT_STATE); - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - VerifyOrExit(strlen(mCurAddr->ifa_name) < nameBufSize, err = INET_ERROR_NO_MEMORY); - strncpy(nameBuf, mCurAddr->ifa_name, nameBufSize); - err = INET_NO_ERROR; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - err = mIntfIter.GetInterfaceName(nameBuf, nameBufSize); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -exit: - return err; -} - -/** - * @fn bool InterfaceAddressIterator::IsUp(void) - * - * @brief Returns whether the network interface associated with the current - * interface address is up. - * - * @return \c true if current network interface is up, \c false if not, or - * if the iterator is not positioned on an interface address. - */ -bool InterfaceAddressIterator::IsUp(void) -{ - if (HasCurrent()) - { -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return (mCurAddr->ifa_flags & IFF_UP) != 0; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - return mIntfIter.IsUp(); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - } - return false; -} - -/** - * @fn bool InterfaceAddressIterator::SupportsMulticast(void) - * - * @brief Returns whether the network interface associated with the current - * interface address supports multicast. - * - * @return \c true if multicast is supported, \c false if not, or - * if the iterator is not positioned on an interface address. - */ -bool InterfaceAddressIterator::SupportsMulticast(void) -{ - if (HasCurrent()) - { -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return (mCurAddr->ifa_flags & IFF_MULTICAST) != 0; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - return mIntfIter.SupportsMulticast(); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - } - return false; -} - -/** - * @fn bool InterfaceAddressIterator::HasBroadcastAddress(void) - * - * @brief Returns whether the network interface associated with the current - * interface address has an IPv4 broadcast address. - * - * @return \c true if the interface has a broadcast address, \c false if not, or - * if the iterator is not positioned on an interface address. - */ -bool InterfaceAddressIterator::HasBroadcastAddress(void) -{ - if (HasCurrent()) - { -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return (mCurAddr->ifa_flags & IFF_BROADCAST) != 0; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - return mIntfIter.HasBroadcastAddress(); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - } - return false; -} - -/** - * @fn void InterfaceAddressIterator::GetAddressWithPrefix(IPPrefix & addrWithPrefix) - * - * @brief Returns an IPPrefix containing the address and prefix length - * for the current address. - */ -void InterfaceAddressIterator::GetAddressWithPrefix(IPPrefix & addrWithPrefix) -{ - if (HasCurrent()) - { - addrWithPrefix.IPAddr = GetAddress(); - addrWithPrefix.Length = GetPrefixLength(); - } - else - { - addrWithPrefix = IPPrefix::Zero; - } -} - -/** - * @fn uint8_t NetmaskToPrefixLength(const uint8_t * netmask, uint16_t netmaskLen) - * - * @brief Compute a prefix length from a variable-length netmask. - */ -uint8_t NetmaskToPrefixLength(const uint8_t * netmask, uint16_t netmaskLen) -{ - uint8_t prefixLen = 0; - - for (uint8_t i = 0; i < netmaskLen; i++, prefixLen += 8) - { - uint8_t b = netmask[i]; - if (b != 0xFF) - { - if ((b & 0xF0) == 0xF0) - prefixLen += 4; - else - b = b >> 4; - - if ((b & 0x0C) == 0x0C) - prefixLen += 2; - else - b = b >> 2; - - if ((b & 0x02) == 0x02) - prefixLen++; - - break; - } - } - - return prefixLen; -} - -} // namespace Inet -} // namespace chip diff --git a/src/inet/InetInterface.h b/src/inet/InetInterface.h deleted file mode 100644 index b186fbfa637319..00000000000000 --- a/src/inet/InetInterface.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - * - * - * - * 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 the Inet::InterfaceId type alias and related - * classes for iterating on the list of system network interfaces and the list - * of system interface addresses. - */ - -#ifndef INETINTERFACE_H -#define INETINTERFACE_H - -#include -#include - -#include -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -struct if_nameindex; -struct ifaddrs; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -namespace chip { -namespace Inet { - -class IPAddress; -class IPPrefix; - - -/** - * @typedef InterfaceId - * - * @brief Indicator for system network interfaces. - * - * @details - * Portability depends on never witnessing this alias. It may be replaced by a - * concrete opaque class in the future. - * - * Note Well: The term "interface identifier" also conventionally refers to - * the lower 64 bits of an IPv6 address in all the relevant IETF standards - * documents, where the abbreviation "IID" is often used. In this text, the - * term "interface indicator" refers to values of this type alias. - */ - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -typedef struct netif *InterfaceId; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -typedef unsigned InterfaceId; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - -/** - * @def INET_NULL_INTERFACEID - * - * @brief The distinguished value indicating no network interface. - * - * @details - * Note Well: This is not the indicator of a "null" network interface. This - * value can be used to indicate the absence of a specific network interface, - * or to specify that any applicable network interface is acceptable. Usage - * varies depending on context. - */ - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#define INET_NULL_INTERFACEID NULL -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#define INET_NULL_INTERFACEID 0 -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - -/** - * @brief Test \c ID for inequivalence with \c INET_NULL_INTERFACEID - * - * @details - * This macro resolves to an expression that evaluates \c false if the - * argument is equivalent to \c INET_NULL_INTERFACEID and \c true otherwise. - */ -#define IsInterfaceIdPresent(intfId) ((intfId) != INET_NULL_INTERFACEID) - -extern INET_ERROR GetInterfaceName(InterfaceId intfId, char *nameBuf, size_t nameBufSize); -extern INET_ERROR InterfaceNameToId(const char *intfName, InterfaceId& intfId); -extern uint8_t NetmaskToPrefixLength(const uint8_t * netmask, uint16_t netmaskLen); - -/** - * @brief Iterator for the list of system network interfaces. - * - * @details - * Use objects of this class to iterate the list of system network interfaces. - * - * Methods on an individual instance of this class are *not* thread-safe; - * however separate instances may be used simultaneously by multiple threads. - * - * On multi-threaded LwIP systems, instances are thread-safe relative to other - * threads accessing the global LwIP state provided that the other threads hold - * the LwIP core lock while mutating the list of netifs, and that netif object - * themselves are never destroyed. - * - * On sockets-based systems, iteration is always stable in the face of changes - * to the underlying system's interfaces. - * - * On LwIP systems, iteration is stable except in the case where the currently - * selected interface is removed from the list, in which case iteration ends - * immediately. - */ -class InterfaceIterator -{ -public: - InterfaceIterator(void); - ~InterfaceIterator(void); - - bool HasCurrent(void); - bool Next(void); - InterfaceId GetInterface(void); - InterfaceId GetInterfaceId(void); - INET_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize); - bool IsUp(void); - bool SupportsMulticast(void); - bool HasBroadcastAddress(void); - -protected: -#if CHIP_SYSTEM_CONFIG_USE_LWIP - struct netif * mCurNetif; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - struct if_nameindex * mIntfArray; - size_t mCurIntf; - short mIntfFlags; - bool mIntfFlagsCached; - - short GetFlags(void); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -}; - -/** - * @brief Iterator for the list of system network interface IP addresses. - * - * @details - * Use objects of this class to iterate the list of system network interface - * interface IP addresses. - * - * Methods on an individual instance of this class are *not* thread-safe; - * however separate instances may be used simultaneously by multiple threads. - * - * On multi-threaded LwIP systems, instances are thread-safe relative to other - * threads accessing the global LwIP state provided that: 1) other threads hold - * the LwIP core lock while mutating the list of netifs; and 2) netif object - * themselves are never destroyed. - * - * On sockets-based systems, iteration is always stable in the face of changes - * to the underlying system's interfaces and/or addresses. - * - * On LwIP systems, iteration is stable except in the case where the interface - * associated with the current address is removed, in which case iteration may - * end prematurely. - */ -class DLL_EXPORT InterfaceAddressIterator -{ -public: - InterfaceAddressIterator(void); - ~InterfaceAddressIterator(void); - - bool HasCurrent(void); - bool Next(void); - IPAddress GetAddress(void); - uint8_t GetPrefixLength(void); - uint8_t GetIPv6PrefixLength(void); - void GetAddressWithPrefix(IPPrefix & addrWithPrefix); - InterfaceId GetInterface(void); - InterfaceId GetInterfaceId(void); - INET_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize); - bool IsUp(void); - bool SupportsMulticast(void); - bool HasBroadcastAddress(void); - -private: -#if CHIP_SYSTEM_CONFIG_USE_LWIP - enum - { - kBeforeStartIndex = -1 - }; - - InterfaceIterator mIntfIter; - int mCurAddrIndex; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - struct ifaddrs * mAddrsList; - struct ifaddrs * mCurAddr; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -}; - - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -inline InterfaceIterator::InterfaceIterator(void) -{ - mCurNetif = netif_list; -} - -inline InterfaceIterator::~InterfaceIterator(void) -{ -} - -inline bool InterfaceIterator::HasCurrent(void) -{ - return mCurNetif != NULL; -} - -inline InterfaceId InterfaceIterator::GetInterfaceId(void) -{ - return mCurNetif; -} - -inline InterfaceAddressIterator::InterfaceAddressIterator(void) -{ - mCurAddrIndex = kBeforeStartIndex; -} - -inline InterfaceAddressIterator::~InterfaceAddressIterator(void) -{ -} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - - -/** - * @brief Deprecated alias for \c GetInterfaceId(void) - */ -inline InterfaceId InterfaceIterator::GetInterface(void) -{ - return GetInterfaceId(); -} - -/** - * @brief Deprecated alias for \c GetInterfaceId(void) - */ -inline InterfaceId InterfaceAddressIterator::GetInterface(void) -{ - return GetInterfaceId(); -} - -/** - * @brief Deprecated alias for \c GetPrefixLength(void) - */ -inline uint8_t InterfaceAddressIterator::GetIPv6PrefixLength(void) -{ - return GetPrefixLength(); -} - -} // namespace Inet -} // namespace chip - -#endif /* INETINTERFACE_H */ diff --git a/src/inet/InetLayer.cpp b/src/inet/InetLayer.cpp deleted file mode 100644 index c9501b6439dfef..00000000000000 --- a/src/inet/InetLayer.cpp +++ /dev/null @@ -1,1872 +0,0 @@ -/* - * - * - * - * 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 or LwIP. - * - * 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 handle via events / - * messages and platform- and system-specific hooks for the event - * / message system. - * - */ - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif - -#include -#include "InetFaultInjection.h" -#include - -#include -#include - -#include -#include -#include -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#include -#ifdef __ANDROID__ -#include -#else -#include -#endif // __ANDROID__ -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#if CHIP_SYSTEM_CONFIG_USE_LWIP && !INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS - -// MARK: InetLayer platform- and system-specific functions for LwIP-native eventing. - -struct LwIPInetEvent -{ - Inet::InetEventType Type; - Inet::InetLayerBasis* Target; - uintptr_t Arg; -}; - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP && !INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -namespace chip { -namespace Inet { - -void InetLayer::UpdateSnapshot(chip::System::Stats::Snapshot &aSnapshot) -{ -#if INET_CONFIG_ENABLE_DNS_RESOLVER - DNSResolver::sPool.GetStatistics(aSnapshot.mResourcesInUse[chip::System::Stats::kInetLayer_NumDNSResolvers], - aSnapshot.mHighWatermarks[chip::System::Stats::kInetLayer_NumDNSResolvers]); -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - TCPEndPoint::sPool.GetStatistics(aSnapshot.mResourcesInUse[chip::System::Stats::kInetLayer_NumTCPEps], - aSnapshot.mHighWatermarks[chip::System::Stats::kInetLayer_NumTCPEps]); -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - UDPEndPoint::sPool.GetStatistics(aSnapshot.mResourcesInUse[chip::System::Stats::kInetLayer_NumUDPEps], - aSnapshot.mHighWatermarks[chip::System::Stats::kInetLayer_NumUDPEps]); -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT -#if INET_CONFIG_ENABLE_RAW_ENDPOINT - RawEndPoint::sPool.GetStatistics(aSnapshot.mResourcesInUse[chip::System::Stats::kInetLayer_NumRawEps], - aSnapshot.mHighWatermarks[chip::System::Stats::kInetLayer_NumRawEps]); -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT -#if INET_CONFIG_ENABLE_TUN_ENDPOINT - TunEndPoint::sPool.GetStatistics(aSnapshot.mResourcesInUse[chip::System::Stats::kInetLayer_NumTunEps], - aSnapshot.mHighWatermarks[chip::System::Stats::kInetLayer_NumTunEps]); -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT -} - -/** - * This is the InetLayer default constructor. - * - * It performs some basic data member initialization; however, since - * InetLayer follows an explicit initializer design pattern, the InetLayer::Init - * method must be called successfully prior to using the object. - * - */ -InetLayer::InetLayer(void) -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - : mImplicitSystemLayer() -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -{ - State = kState_NotInitialized; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - if (!sInetEventHandlerDelegate.IsInitialized()) - sInetEventHandlerDelegate.Init(HandleInetLayerEvent); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -chip::System::LwIPEventHandlerDelegate InetLayer::sInetEventHandlerDelegate; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if INET_CONFIG_MAX_DROPPABLE_EVENTS && CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_NO_LOCKING - -INET_ERROR InetLayer::InitQueueLimiter(void) -{ - mDroppableEvents = 0; - return INET_NO_ERROR; -} - -bool InetLayer::CanEnqueueDroppableEvent(void) -{ - if (__sync_add_and_fetch(&mDroppableEvents, 1) <= INET_CONFIG_MAX_DROPPABLE_EVENTS) - { - return true; - } - else - { - __sync_add_and_fetch(&mDroppableEvents, -1); - return false; - } -} - -void InetLayer::DroppableEventDequeued(void) -{ - __sync_add_and_fetch(&mDroppableEvents, -1); -} - -#elif CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING - -INET_ERROR InetLayer::InitQueueLimiter(void) -{ - const unsigned portBASE_TYPE maximum = INET_CONFIG_MAX_DROPPABLE_EVENTS; - const unsigned portBASE_TYPE initial = INET_CONFIG_MAX_DROPPABLE_EVENTS; - -#if (configSUPPORT_STATIC_ALLOCATION == 1) - mDroppableEvents = xSemaphoreCreateCountingStatic(maximum, initial, &mDroppableEventsObj); -#else - mDroppableEvents = xSemaphoreCreateCounting(maximum, initial); -#endif - - if (mDroppableEvents != NULL) - return INET_NO_ERROR; - else - return INET_ERROR_NO_MEMORY; -} - -bool InetLayer::CanEnqueueDroppableEvent(void) -{ - if (xSemaphoreTake(mDroppableEvents, 0) != pdTRUE) - { - return false; - } - return true; -} - -void InetLayer::DroppableEventDequeued(void) -{ - xSemaphoreGive(mDroppableEvents); -} - -#else // !CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING - -INET_ERROR InetLayer::InitQueueLimiter(void) -{ - if (sem_init(&mDroppableEvents, 0, INET_CONFIG_MAX_DROPPABLE_EVENTS) != 0) - { - return chip::System::MapErrorPOSIX(errno); - } - return INET_NO_ERROR; -} - -bool InetLayer::CanEnqueueDroppableEvent(void) -{ - // Striclty speaking, we should check for EAGAIN. But, other - // errno values probably should signal that that we should drop - // the packet: EINVAL means that the semaphore is not valid (we - // failed initialization), and EINTR should probably also lead to - // dropping a packet. - - if (sem_trywait(&mDroppableEvents) != 0) - { - return false; - } - return true; -} - -void InetLayer::DroppableEventDequeued(void) -{ - sem_post(&mDroppableEvents); -} - -#endif // !CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING -#endif // INET_CONFIG_MAX_DROPPABLE_EVENTS && CHIP_SYSTEM_CONFIG_USE_LWIP - -/** - * This is the InetLayer explicit initializer. This must be called - * and complete successfully before the InetLayer may be used. - * - * The caller may provide an optional context argument which will be - * passed back via any platform-specific hook functions. For - * LwIP-based adaptations, this will typically be a pointer to the - * event queue associated with the InetLayer instance. - * - * Platforms may choose to assert - * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS in their - * platform-specific configuration header and enable the - * Platform::InetLayer::WillInit and Platform::InetLayer::DidInit - * hooks to effect platform-specific customizations or data extensions - * to InetLayer. - * - * @param[in] aSystemLayer A required instance of the chip System Layer - * already successfully initialized. - * - * @param[in] aContext An optional context argument which will be passed - * back to the caller via any platform-specific hook - * functions. - * - * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer is in an - * incorrect state. - * @retval #INET_ERROR_NO_MEMORY If the InetLayer runs out - * of resource for this - * request for a new timer. - * @retval other Platform-specific errors indicating the reason for - * initialization failure. - * @retval #INET_NO_ERROR On success. - * - */ -INET_ERROR InetLayer::Init(chip::System::Layer& aSystemLayer, void *aContext) -{ - INET_ERROR err = INET_NO_ERROR; - - RegisterInetLayerErrorFormatter(); - - if (State != kState_NotInitialized) - return INET_ERROR_INCORRECT_STATE; - - // Platform-specific initialization may elect to set this data - // member. Ensure it is set to a sane default value before - // invoking platform-specific initialization. - - mPlatformData = NULL; - - Platform::InetLayer::WillInit(this, aContext); - SuccessOrExit(err); - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - if (&aSystemLayer == &mImplicitSystemLayer) - { - err = mImplicitSystemLayer.Init(aContext); - SuccessOrExit(err); - } -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - - mSystemLayer = &aSystemLayer; - mContext = aContext; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - err = InitQueueLimiter(); - SuccessOrExit(err); - - mSystemLayer->AddEventHandlerDelegate(sInetEventHandlerDelegate); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - - State = kState_Initialized; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#if INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - - err = mAsyncDNSResolver.Init(this); - SuccessOrExit(err); - -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - exit: - Platform::InetLayer::DidInit(this, mContext, err); - return err; -} - -/** - * This is the InetLayer explicit deinitializer and should be called - * prior to disposing of an instantiated InetLayer instance. - * - * Platforms may choose to assert - * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS in their - * platform-specific configuration header and enable the - * Platform::InetLayer::WillShutdown and - * Platform::InetLayer::DidShutdown hooks to effect clean-up of - * platform-specific customizations or data extensions to InetLayer. - * - * @return #INET_NO_ERROR on success; otherwise, a specific error indicating - * the reason for shutdown failure. - * - */ -INET_ERROR InetLayer::Shutdown(void) -{ - INET_ERROR err; - - err = Platform::InetLayer::WillShutdown(this, mContext); - SuccessOrExit(err); - - if (State == kState_Initialized) - { -#if INET_CONFIG_ENABLE_DNS_RESOLVER - // Cancel all DNS resolution requests owned by this instance. - for (size_t i = 0; i < DNSResolver::sPool.Size(); i++) - { - DNSResolver* lResolver = DNSResolver::sPool.Get(*mSystemLayer, i); - if ((lResolver != NULL) && lResolver->IsCreatedByInetLayer(*this)) - { - lResolver->Cancel(); - } - } - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - - err = mAsyncDNSResolver.Shutdown(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER - -#if INET_CONFIG_ENABLE_RAW_ENDPOINT - // Close all raw endpoints owned by this Inet layer instance. - for (size_t i = 0; i < RawEndPoint::sPool.Size(); i++) - { - RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->Close(); - } - } -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - // Abort all TCP endpoints owned by this instance. - for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) - { - TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->Abort(); - } - } -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - // Close all UDP endpoints owned by this instance. - for (size_t i = 0; i < UDPEndPoint::sPool.Size(); i++) - { - UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->Close(); - } - } -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - if (mSystemLayer == &mImplicitSystemLayer) - { - err = mImplicitSystemLayer.Shutdown(); - SuccessOrExit(err); - } -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - - } - - State = kState_NotInitialized; - -exit: - Platform::InetLayer::DidShutdown(this, mContext, err); - - return err; -} - -/** - * This returns any client-specific platform data assigned to the - * instance, if it has been previously set. - * - * @return Client-specific platform data, if is has been previously set; - * otherwise, NULL. - * - */ -void *InetLayer::GetPlatformData(void) -{ - return mPlatformData; -} - -/** - * This sets the specified client-specific platform data to the - * instance for later retrieval by the client platform. - * - * @param[in] aPlatformData The client-specific platform data to set. - * - */ -void InetLayer::SetPlatformData(void *aPlatformData) -{ - mPlatformData = aPlatformData; -} - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 -bool InetLayer::IsIdleTimerRunning(void) -{ - bool timerRunning = false; - - // see if there are any TCP connections with the idle timer check in use. - for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) - { - TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); - - if ((lEndPoint != NULL) && (lEndPoint->mIdleTimeout != 0)) - { - timerRunning = true; - break; - } - } - - return timerRunning; -} -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 - -/** - * Get the link local IPv6 address for a specified link or interface. - * - * @param[in] link The interface for which the link local IPv6 - * address is being sought. - * - * @param[out] llAddr The link local IPv6 address for the link. - * - * @retval #INET_ERROR_NOT_IMPLEMENTED If IPv6 is not supported. - * @retval #INET_ERROR_BAD_ARGS If the link local address - * is NULL. - * @retval #INET_ERROR_ADDRESS_NOT_FOUND If the link does not have - * any address configured. - * @retval #INET_NO_ERROR On success. - * - */ -INET_ERROR InetLayer::GetLinkLocalAddr(InterfaceId link, IPAddress *llAddr) -{ - INET_ERROR err = INET_NO_ERROR; -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if !LWIP_IPV6 - err = INET_ERROR_NOT_IMPLEMENTED; - goto out; -#endif //!LWIP_IPV6 -#endif //CHIP_SYSTEM_CONFIG_USE_LWIP - - if ( llAddr == NULL ) - { - err = INET_ERROR_BAD_ARGS; - goto out; - } - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - for (struct netif *intf = netif_list; intf != NULL; intf = intf->next) - { - if ( (link != NULL) && (link != intf) ) continue; - int j; for (j = 0; j < LWIP_IPV6_NUM_ADDRESSES; ++j) - { - if (ip6_addr_isvalid(netif_ip6_addr_state(intf, j)) && ip6_addr_islinklocal(netif_ip6_addr(intf, j))) - { - (*llAddr) = IPAddress::FromIPv6(*netif_ip6_addr(intf, j)); - goto out; - } - } - if (link != NULL) { - err = INET_ERROR_ADDRESS_NOT_FOUND; - break; - } - } -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - struct ifaddrs *ifaddr; - int rv; - rv = getifaddrs(&ifaddr); - if (rv != -1) - { - struct ifaddrs*ifaddr_iter = ifaddr; - while (ifaddr_iter != NULL) - { - - if (ifaddr_iter->ifa_addr != NULL) - { - if ((ifaddr_iter->ifa_addr->sa_family == AF_INET6) && - ((link == INET_NULL_INTERFACEID) || (if_nametoindex(ifaddr_iter->ifa_name) == link))) - { - struct in6_addr *sin6_addr = &((struct sockaddr_in6*)ifaddr_iter->ifa_addr)->sin6_addr; - if (sin6_addr->s6_addr[0] == 0xfe && (sin6_addr->s6_addr[1] & 0xc0) == 0x80)//Link Local Address - { - (*llAddr) = IPAddress::FromIPv6(((struct sockaddr_in6*)ifaddr_iter->ifa_addr)->sin6_addr); - break; - } - } - } - ifaddr_iter = ifaddr_iter->ifa_next; - } - freeifaddrs(ifaddr); - } - else - { - err = INET_ERROR_ADDRESS_NOT_FOUND; - } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -out: - return err; -} - -#if INET_CONFIG_ENABLE_RAW_ENDPOINT -/** - * Creates a new RawEndPoint object for a specific IP version and protocol. - * - * @note - * This function gets a free RawEndPoint object from a pre-allocated pool - * and also calls the explicit initializer on the new object. - * - * @param[in] ipVer IPv4 or IPv6. - * - * @param[in] ipProto A protocol within the IP family (e.g., ICMPv4 or ICMPv6). - * - * @param[inout] retEndPoint A pointer to a pointer of the RawEndPoint object that is - * a return parameter upon completion of the object creation. - * *retEndPoint is NULL if creation fails. - * - * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. - * @retval #INET_ERROR_NO_ENDPOINTS If the InetLayer RawEndPoint pool is full and no new - * endpoints can be created. - * @retval #INET_NO_ERROR On success. - * - */ -INET_ERROR InetLayer::NewRawEndPoint(IPVersion ipVer, IPProtocol ipProto, RawEndPoint **retEndPoint) -{ - INET_ERROR err = INET_NO_ERROR; - *retEndPoint = NULL; - - VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); - - *retEndPoint = RawEndPoint::sPool.TryCreate(*mSystemLayer); - if (*retEndPoint != NULL) - { - (*retEndPoint)->Inet::RawEndPoint::Init(this, ipVer, ipProto); - SYSTEM_STATS_INCREMENT(chip::System::Stats::kInetLayer_NumRawEps); - } - else - { - chipLogError(Inet, "%s endpoint pool FULL", "Raw"); - err = INET_ERROR_NO_ENDPOINTS; - } - -exit: - return err; -} -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT -/** - * Creates a new TCPEndPoint object. - * - * @note - * This function gets a free TCPEndPoint object from a pre-allocated pool - * and also calls the explicit initializer on the new object. - * - * @param[inout] retEndPoint A pointer to a pointer of the TCPEndPoint object that is - * a return parameter upon completion of the object creation. - * *retEndPoint is NULL if creation fails. - * - * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. - * @retval #INET_ERROR_NO_ENDPOINTS If the InetLayer TCPEndPoint pool is full and no new - * endpoints can be created. - * @retval #INET_NO_ERROR On success. - * - */ -INET_ERROR InetLayer::NewTCPEndPoint(TCPEndPoint **retEndPoint) -{ - INET_ERROR err = INET_NO_ERROR; - *retEndPoint = NULL; - - VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); - - *retEndPoint = TCPEndPoint::sPool.TryCreate(*mSystemLayer); - if (*retEndPoint != NULL) - { - (*retEndPoint)->Init(this); - SYSTEM_STATS_INCREMENT(chip::System::Stats::kInetLayer_NumTCPEps); - } - else - { - chipLogError(Inet, "%s endpoint pool FULL", "TCP"); - err = INET_ERROR_NO_ENDPOINTS; - } - -exit: - return err; -} -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT -/** - * Creates a new UDPEndPoint object. - * - * @note - * This function gets a free UDPEndPoint object from a pre-allocated pool - * and also calls the explicit initializer on the new object. - * - * @param[inout] retEndPoint A pointer to a pointer of the UDPEndPoint object that is - * a return parameter upon completion of the object creation. - * *retEndPoint is NULL if creation fails. - * - * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. - * @retval #INET_ERROR_NO_ENDPOINTS If the InetLayer UDPEndPoint pool is full and no new - * endpoints can be created. - * @retval #INET_NO_ERROR On success. - * - */ -INET_ERROR InetLayer::NewUDPEndPoint(UDPEndPoint **retEndPoint) -{ - INET_ERROR err = INET_NO_ERROR; - *retEndPoint = NULL; - - VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); - - *retEndPoint = UDPEndPoint::sPool.TryCreate(*mSystemLayer); - if (*retEndPoint != NULL) - { - (*retEndPoint)->Init(this); - SYSTEM_STATS_INCREMENT(chip::System::Stats::kInetLayer_NumUDPEps); - } - else - { - chipLogError(Inet, "%s endpoint pool FULL", "UDP"); - err = INET_ERROR_NO_ENDPOINTS; - } - -exit: - return err; -} -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -#if INET_CONFIG_ENABLE_TUN_ENDPOINT -/** - * Creates a new TunEndPoint object. - * - * @note - * This function gets a free TunEndPoint object from a pre-allocated pool - * and also calls the explicit initializer on the new object. - * - * @param[inout] retEndPoint A pointer to a pointer of the TunEndPoint object that is - * a return parameter upon completion of the object creation. - * *retEndPoint is NULL if creation fails. - * - * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. - * @retval #INET_ERROR_NO_ENDPOINTS If the InetLayer TunEndPoint pool is full and no new - * ones can be created. - * @retval #INET_NO_ERROR On success. - * - */ -INET_ERROR InetLayer::NewTunEndPoint(TunEndPoint **retEndPoint) -{ - INET_ERROR err = INET_NO_ERROR; - *retEndPoint = NULL; - - VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); - - *retEndPoint = TunEndPoint::sPool.TryCreate(*mSystemLayer); - if (*retEndPoint != NULL) - { - (*retEndPoint)->Init(this); - SYSTEM_STATS_INCREMENT(chip::System::Stats::kInetLayer_NumTunEps); - } - else - { - chipLogError(Inet, "%s endpoint pool FULL", "Tun"); - err = INET_ERROR_NO_ENDPOINTS; - } - -exit: - return err; -} -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT - -#if INET_CONFIG_ENABLE_DNS_RESOLVER -/** - * Perform an IP address resolution of a specified hostname. - * - * @note - * This is an asynchronous operation and the result will be communicated back - * via the OnComplete() callback. - * - * @param[in] hostName A pointer to a NULL-terminated C string representing - * the host name to be queried. - * - * @param[in] maxAddrs The maximum number of addresses to store in the DNS - * table. - * - * @param[in] addrArray A pointer to the DNS table. - * - * @param[in] onComplete A pointer to the callback function when a DNS - * request is complete. - * - * @param[in] appState A pointer to the application state to be passed to - * onComplete when a DNS request is complete. - * - * @retval #INET_NO_ERROR if a DNS request is handled - * successfully. - * @retval #INET_ERROR_NO_MEMORY if the Inet layer resolver pool - * is full. - * @retval #INET_ERROR_HOST_NAME_TOO_LONG if a requested host name is too - * long. - * @retval #INET_ERROR_HOST_NOT_FOUND if a request host name could not be - * resolved to an address. - * @retval #INET_ERROR_DNS_TRY_AGAIN if a name server returned a - * temporary failure indication; - * try again later. - * @retval #INET_ERROR_DNS_NO_RECOVERY if a name server returned an - * unrecoverable error. - * @retval #INET_ERROR_NOT_IMPLEMENTED if DNS resolution is not enabled on - * the underlying platform. - * @retval other POSIX network or OS error returned by the underlying DNS - * resolver implementation. - * - */ -INET_ERROR InetLayer::ResolveHostAddress(const char *hostName, uint8_t maxAddrs, - IPAddress *addrArray, - DNSResolveCompleteFunct onComplete, void *appState) -{ - return ResolveHostAddress(hostName, strlen(hostName), maxAddrs, addrArray, onComplete, appState); -} - -/** - * Perform an IP address resolution of a specified hostname. - * - * @param[in] hostName A pointer to a non NULL-terminated C string representing the host name - * to be queried. - * - * @param[in] hostNameLen The string length of host name. - * - * @param[in] maxAddrs The maximum number of addresses to store in the DNS - * table. - * - * @param[in] addrArray A pointer to the DNS table. - * - * @param[in] onComplete A pointer to the callback function when a DNS - * request is complete. - * - * @param[in] appState A pointer to the application state to be passed to - * onComplete when a DNS request is complete. - * - * @retval #INET_NO_ERROR if a DNS request is handled - * successfully. - * @retval #INET_ERROR_NO_MEMORY if the Inet layer resolver pool - * is full. - * @retval #INET_ERROR_HOST_NAME_TOO_LONG if a requested host name is too - * long. - * @retval #INET_ERROR_HOST_NOT_FOUND if a request host name could not be - * resolved to an address. - * @retval #INET_ERROR_DNS_TRY_AGAIN if a name server returned a - * temporary failure indication; - * try again later. - * @retval #INET_ERROR_DNS_NO_RECOVERY if a name server returned an - * unrecoverable error. - * @retval #INET_ERROR_NOT_IMPLEMENTED if DNS resolution is not enabled on - * the underlying platform. - * @retval other POSIX network or OS error returned by the underlying DNS - * resolver implementation. - * - */ -INET_ERROR InetLayer::ResolveHostAddress(const char *hostName, uint16_t hostNameLen, - uint8_t maxAddrs, IPAddress *addrArray, - DNSResolveCompleteFunct onComplete, void *appState) -{ - return ResolveHostAddress(hostName, hostNameLen, kDNSOption_Default, maxAddrs, addrArray, onComplete, appState); -} - -/** - * Perform an IP address resolution of a specified hostname. - * - * @param[in] hostName A pointer to a non NULL-terminated C string representing the host name - * to be queried. - * - * @param[in] hostNameLen The string length of host name. - * - * @param[in] options An integer value controlling how host name resolution is performed. - * - * Value should be one of the address family values from the - * #DNSOptions enumeration: - * - * #kDNSOption_AddrFamily_Any - * #kDNSOption_AddrFamily_IPv4Only - * #kDNSOption_AddrFamily_IPv6Only - * #kDNSOption_AddrFamily_IPv4Preferred - * #kDNSOption_AddrFamily_IPv6Preferred - * - * @param[in] maxAddrs The maximum number of addresses to store in the DNS - * table. - * - * @param[in] addrArray A pointer to the DNS table. - * - * @param[in] onComplete A pointer to the callback function when a DNS - * request is complete. - * - * @param[in] appState A pointer to the application state to be passed to - * onComplete when a DNS request is complete. - * - * @retval #INET_NO_ERROR if a DNS request is handled - * successfully. - * @retval #INET_ERROR_NO_MEMORY if the Inet layer resolver pool - * is full. - * @retval #INET_ERROR_HOST_NAME_TOO_LONG if a requested host name is too - * long. - * @retval #INET_ERROR_HOST_NOT_FOUND if a request host name could not be - * resolved to an address. - * @retval #INET_ERROR_DNS_TRY_AGAIN if a name server returned a - * temporary failure indication; - * try again later. - * @retval #INET_ERROR_DNS_NO_RECOVERY if a name server returned an - * unrecoverable error. - * @retval #INET_ERROR_NOT_IMPLEMENTED if DNS resolution is not enabled on - * the underlying platform. - * @retval other POSIX network or OS error returned by the underlying DNS - * resolver implementation. - * - */ -INET_ERROR InetLayer::ResolveHostAddress(const char *hostName, uint16_t hostNameLen, - uint8_t options, - uint8_t maxAddrs, IPAddress *addrArray, - DNSResolveCompleteFunct onComplete, void *appState) -{ - INET_ERROR err = INET_NO_ERROR; - DNSResolver *resolver = NULL; - - VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); - - INET_FAULT_INJECT(FaultInjection::kFault_DNSResolverNew, return INET_ERROR_NO_MEMORY); - - // Store context information and set the resolver state. - VerifyOrExit(hostNameLen <= NL_DNS_HOSTNAME_MAX_LEN, err = INET_ERROR_HOST_NAME_TOO_LONG); - VerifyOrExit(maxAddrs > 0, err = INET_ERROR_NO_MEMORY); - - resolver = DNSResolver::sPool.TryCreate(*mSystemLayer); - if (resolver != NULL) - { - resolver->InitInetLayerBasis(*this); - } - else - { - chipLogError(Inet, "%s resolver pool FULL", "DNS"); - ExitNow(err = INET_ERROR_NO_MEMORY); - } - - // Short-circuit full address resolution if the supplied host name is a text-form - // IP address... - if (IPAddress::FromString(hostName, hostNameLen, *addrArray)) - { - uint8_t addrTypeOption = (options & kDNSOption_AddrFamily_Mask); - IPAddressType addrType = addrArray->Type(); - - if ((addrTypeOption == kDNSOption_AddrFamily_IPv6Only && addrType != kIPAddressType_IPv6) -#if INET_CONFIG_ENABLE_IPV4 - || (addrTypeOption == kDNSOption_AddrFamily_IPv4Only && addrType != kIPAddressType_IPv4) -#endif - ) - { - err = INET_ERROR_INCOMPATIBLE_IP_ADDRESS_TYPE; - } - - if (onComplete) - { - onComplete(appState, err, (err == INET_NO_ERROR) ? 1 : 0, addrArray); - } - - resolver->Release(); - resolver = NULL; - - ExitNow(err = INET_NO_ERROR); - } - - // After this point, the resolver will be released by: - // - mAsyncDNSResolver (in case of ASYNC_DNS_SOCKETS) - // - resolver->Resolve() (in case of synchronous resolving) - // - the event handlers (in case of LwIP) - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - - err = mAsyncDNSResolver.PrepareDNSResolver(*resolver, hostName, hostNameLen, options, - maxAddrs, addrArray, onComplete, appState); - SuccessOrExit(err); - - mAsyncDNSResolver.EnqueueRequest(*resolver); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - -#if !INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - err = resolver->Resolve(hostName, hostNameLen, options, maxAddrs, addrArray, onComplete, appState); -#endif // !INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -exit: - - return err; -} - -/** - * Cancel any outstanding DNS query (for a matching completion callback and - * application state) that may still be active. - * - * @note - * This situation can arise if the application initiates a connection - * to a peer using a hostname and then aborts/closes the connection - * before the hostname resolution completes. - * - * @param[in] onComplete A pointer to the callback function when a DNS - * request is complete. - * - * @param[in] appState A pointer to an application state object to be passed - * to the callback function as argument. - * - */ -void InetLayer::CancelResolveHostAddress(DNSResolveCompleteFunct onComplete, void *appState) -{ - if (State != kState_Initialized) - return; - - for (size_t i = 0; i < DNSResolver::sPool.Size(); i++) - { - DNSResolver* lResolver = DNSResolver::sPool.Get(*mSystemLayer, i); - - if (lResolver == NULL) - { - continue; - } - - if (!lResolver->IsCreatedByInetLayer(*this)) - { - continue; - } - - if (lResolver->OnComplete != onComplete) - { - continue; - } - - if (lResolver->AppState != appState) - { - continue; - } - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - if (lResolver->mState == DNSResolver::kState_Canceled) - { - continue; - } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS - - lResolver->Cancel(); - break; - } -} - -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -static void SystemTimerComplete(chip::System::Layer* aLayer, void* aAppState, chip::System::Error aError) -{ - chip::System::Timer& lTimer = *reinterpret_cast(aAppState); - InetLayer& lInetLayer = *lTimer.InetLayer(); - InetLayer::TimerCompleteFunct lComplete = reinterpret_cast(lTimer.OnCompleteInetLayer()); - void* lAppState = lTimer.AppStateInetLayer(); - - lComplete(&lInetLayer, lAppState, static_cast(aError)); -} - -/** -* @brief -* This method registers a one-shot timer(to fire at a specified offset relative to the time -* of registration) with the underlying timer mechanism, through this InetLayer instance. -* -* @note -* Each InetLayer instance could have its own set of timers. This might not be -* significant to applications, as each application usually works with one singleton -* InetLayer instance. -* -* @param[in] aMilliseconds Number of milliseconds before this timer should fire. -* -* @param[in] aComplete A pointer to a callback function to be called when this -* timer fires. -* -* @param[in] aAppState A pointer to an application state object to be passed -* to the callback function as argument. -* -* @retval #INET_ERROR_INCORRECT_STATE If the InetLayer instance is not initialized. -* @retval #INET_ERROR_NO_MEMORY If the InetLayer runs out of resource for this -* request for a new timer. -* @retval #INET_NO_ERROR On success. -* -*/ -INET_ERROR InetLayer::StartTimer(uint32_t aMilliseconds, TimerCompleteFunct aComplete, void* aAppState) -{ - INET_ERROR lReturn; - - if (State != kState_Initialized) - { - return INET_ERROR_INCORRECT_STATE; - } - - chip::System::Timer* lTimer; - - lReturn = mSystemLayer->NewTimer(lTimer); - SuccessOrExit(lReturn); - - lTimer->AttachInetLayer(*this, reinterpret_cast(aComplete), aAppState); - - lReturn = lTimer->Start(aMilliseconds, SystemTimerComplete, lTimer); - - if (lReturn != CHIP_SYSTEM_NO_ERROR) - { - lTimer->Cancel(); - } - -exit: - switch (lReturn) - { - case CHIP_SYSTEM_ERROR_NO_MEMORY: lReturn = INET_ERROR_NO_MEMORY; break; - case CHIP_SYSTEM_NO_ERROR: lReturn = INET_NO_ERROR; break; - } - - return lReturn; -} - -/** -* @brief -* This method cancels an one-shot timer, started earlier through @p StartTimer(). -* -* @note -* The cancellation could fail silently in two different ways. If the timer -* specified by the combination of the callback function and application state object -* couldn't be found, cancellation could fail. If the timer has fired, but not yet -* removed from memory, cancellation could also fail. -* -* @param[in] aComplete A pointer to the callback function used in calling @p StartTimer(). -* @param[in] aAppState A pointer to the application state object used in calling -* @p StartTimer(). -* -*/ -void InetLayer::CancelTimer(TimerCompleteFunct aComplete, void* aAppState) -{ - if (State == kState_Initialized) - { - mSystemLayer->CancelAllMatchingInetTimers(*this, reinterpret_cast(aComplete), aAppState); - } -} -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -/** - * Get the interface identifier for the specified IP address. If the - * interface identifier cannot be derived it is set to the - * #INET_NULL_INTERFACEID. - * - * @note - * This function fetches the first interface (from the configured list - * of interfaces) that matches the specified IP address. - * - * @param[in] addr A reference to the IPAddress object. - * - * @param[out] intfId A reference to the InterfaceId object. - * - * @return #INET_NO_ERROR unconditionally. - * - */ -INET_ERROR InetLayer::GetInterfaceFromAddr(const IPAddress& addr, InterfaceId& intfId) -{ - InterfaceAddressIterator addrIter; - - for (; addrIter.HasCurrent(); addrIter.Next()) - { - IPAddress curAddr = addrIter.GetAddress(); - if (addr == curAddr) - { - intfId = addrIter.GetInterface(); - return INET_NO_ERROR; - } - } - - intfId = INET_NULL_INTERFACEID; - - return INET_NO_ERROR; -} - -/** - * Check if there is a prefix match between the specified IPv6 address and any of - * the locally configured IPv6 addresses. - * - * @param[in] addr The IPv6 address to check for the prefix-match. - * - * @return true if a successful match is found, otherwise false. - * - */ -bool InetLayer::MatchLocalIPv6Subnet(const IPAddress& addr) -{ - if (addr.IsIPv6LinkLocal()) - return true; - - InterfaceAddressIterator ifAddrIter; - for ( ; ifAddrIter.HasCurrent(); ifAddrIter.Next()) - { - IPPrefix addrPrefix; - addrPrefix.IPAddr = ifAddrIter.GetAddress(); -#if INET_CONFIG_ENABLE_IPV4 - if (addrPrefix.IPAddr.IsIPv4()) - continue; -#endif // INET_CONFIG_ENABLE_IPV4 - if (addrPrefix.IPAddr.IsIPv6LinkLocal()) - continue; - addrPrefix.Length = ifAddrIter.GetIPv6PrefixLength(); - if (addrPrefix.MatchAddress(addr)) - return true; - } - - return false; -} - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 -void InetLayer::HandleTCPInactivityTimer(chip::System::Layer* aSystemLayer, void* aAppState, chip::System::Error aError) -{ - InetLayer& lInetLayer = *reinterpret_cast(aAppState); - bool lTimerRequired = lInetLayer.IsIdleTimerRunning(); - - for (size_t i = 0; i < INET_CONFIG_NUM_TCP_ENDPOINTS; i++) - { - TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*aSystemLayer, i); - - if (lEndPoint == NULL) continue; - if (!lEndPoint->IsCreatedByInetLayer(lInetLayer)) continue; - if (!lEndPoint->IsConnected()) continue; - if (lEndPoint->mIdleTimeout == 0) continue; - - if (lEndPoint->mRemainingIdleTime == 0) - { - lEndPoint->DoClose(INET_ERROR_IDLE_TIMEOUT, false); - } - else - { - --lEndPoint->mRemainingIdleTime; - } - } - - if (lTimerRequired) - { - aSystemLayer->StartTimer(INET_TCP_IDLE_CHECK_INTERVAL, HandleTCPInactivityTimer, &lInetLayer); - } -} -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -chip::System::Error InetLayer::HandleInetLayerEvent(chip::System::Object& aTarget, chip::System::EventType aEventType, - uintptr_t aArgument) -{ - chip::System::Error lReturn = CHIP_SYSTEM_NO_ERROR; - InetLayerBasis& lBasis = static_cast(aTarget); - - VerifyOrExit(INET_IsInetEvent(aEventType), lReturn = CHIP_SYSTEM_ERROR_UNEXPECTED_EVENT); - - // Dispatch the event according to its type. - switch (aEventType) - { -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - case kInetEvent_TCPConnectComplete: - static_cast(aTarget).HandleConnectComplete(static_cast(aArgument)); - break; - - case kInetEvent_TCPConnectionReceived: - static_cast(aTarget).HandleIncomingConnection(reinterpret_cast(aArgument)); - break; - - case kInetEvent_TCPDataReceived: - static_cast(aTarget).HandleDataReceived(reinterpret_cast(aArgument)); - break; - - case kInetEvent_TCPDataSent: - static_cast(aTarget).HandleDataSent(static_cast(aArgument)); - break; - - case kInetEvent_TCPError: - static_cast(aTarget).HandleError(static_cast(aArgument)); - break; -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_RAW_ENDPOINT - case kInetEvent_RawDataReceived: - static_cast(aTarget).HandleDataReceived(reinterpret_cast(aArgument)); - break; -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - case kInetEvent_UDPDataReceived: - static_cast(aTarget).HandleDataReceived(reinterpret_cast(aArgument)); - break; -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -#if INET_CONFIG_ENABLE_TUN_ENDPOINT - case kInetEvent_TunDataReceived: - static_cast(aTarget).HandleDataReceived(reinterpret_cast(aArgument)); - break; -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT - -#if INET_CONFIG_ENABLE_DNS_RESOLVER - case kInetEvent_DNSResolveComplete: - static_cast(aTarget).HandleResolveComplete(); - break; -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER - - default: - lReturn = CHIP_SYSTEM_ERROR_UNEXPECTED_EVENT; - ExitNow(); - } - - // If the event was droppable, record the fact that it has been dequeued. - if (IsDroppableEvent(aEventType)) - { - InetLayer& lInetLayer = lBasis.Layer(); - - lInetLayer.DroppableEventDequeued(); - } - -exit: - return lReturn; -} - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -/** - * This posts an event / message of the specified type with the - * provided argument to this instance's platform-specific event / - * message queue. - * - * @param[inout] target A pointer to the InetLayer object making the - * post request. - * - * @param[in] type The type of event to post. - * - * @param[inout] arg The argument associated with the event to post. - * - * @retval #INET_ERROR_INCORRECT_STATE If the state of the InetLayer - * object is incorrect. - * @retval #INET_ERROR_BAD_ARGS If #target is NULL. - * @retval #INET_ERROR_NO_MEMORY If the EventQueue is already - * full. - * @retval other platform-specific errors generated indicating the reason - * for failure. - * @retval #INET_NO_ERROR On success. - * - */ -INET_ERROR InetLayer::PostEvent(InetLayerBasis *target, InetEventType type, uintptr_t arg) -{ - chip::System::Layer& lSystemLayer = *mSystemLayer; - INET_ERROR retval = INET_NO_ERROR; - - VerifyOrExit(State == kState_Initialized, retval = INET_ERROR_INCORRECT_STATE); - VerifyOrExit(target != NULL, retval = INET_ERROR_BAD_ARGS); - - { - chip::System::Layer& lTargetSystemLayer = target->SystemLayer(); - - VerifyOrDieWithMsg(target->IsRetained(lSystemLayer), Inet, "wrong system layer! [target %p != instance %p]", - &lTargetSystemLayer, &lSystemLayer); - } - - // Sanity check that this instance and the target layer haven't - // been "crossed". - - { - InetLayer& lTargetInetLayer = target->Layer(); - - VerifyOrDieWithMsg(this == &lTargetInetLayer, Inet, "target layer %p != instance layer %p", &lTargetInetLayer, this); - } - - if (IsDroppableEvent(type) && !CanEnqueueDroppableEvent()) - { - chipLogProgress(Inet, "Dropping incoming packet (type %d)", (int)type); - ExitNow(retval = INET_ERROR_NO_MEMORY); - } - - retval = Platform::InetLayer::PostEvent(this, mContext, target, type, arg); - if (retval != INET_NO_ERROR) - { - chipLogError(Inet, "Failed to queue InetLayer event (type %d): %s", (int)type, ErrorStr(retval)); - } - SuccessOrExit(retval); - -exit: - return retval; -} - -/** - * This is a syntactic wrapper around a platform-specific hook that - * effects an event loop, waiting on a queue that services this - * instance, pulling events off of that queue, and then dispatching - * them for handling. - * - * @return #INET_NO_ERROR on success; otherwise, a specific error - * indicating the reason for initialization failure. - * - */ -INET_ERROR InetLayer::DispatchEvents(void) -{ - INET_ERROR retval = INET_NO_ERROR; - - VerifyOrExit(State == kState_Initialized, retval = INET_ERROR_INCORRECT_STATE); - - retval = Platform::InetLayer::DispatchEvents(this, mContext); - SuccessOrExit(retval); - - exit: - return retval; -} - -/** - * Start the platform timer with specified msec duration. - * - * @brief - * Calls the Platform specific API to start a platform timer. - * This API is called by the chip::System::Timer class when one or more - * system timers are active and require deferred execution. - * - * @param[in] inDurMS The timer duration in milliseconds. - * - * @return INET_NO_ERROR on success, error code otherwise. - * - */ -INET_ERROR InetLayer::StartPlatformTimer(uint32_t inDurMS) -{ - INET_ERROR retval; - - VerifyOrExit(State == kState_Initialized, retval = INET_ERROR_INCORRECT_STATE); - - retval = Platform::InetLayer::StartTimer(this, mContext, inDurMS); - - exit: - return retval; -} - -/** - * Handle the platform timer expiration event. - * - * @brief - * Calls chip::System::Timer::HandleExpiredTimers to handle any expired - * system timers. It is assumed that this API is called only while - * on the thread which owns the InetLayer object. - * - * @return INET_NO_ERROR on success, error code otherwise. - * - */ -INET_ERROR InetLayer::HandlePlatformTimer(void) -{ - INET_ERROR lReturn; - chip::System::Error lSystemError; - - VerifyOrExit(State == kState_Initialized, lReturn = INET_ERROR_INCORRECT_STATE); - - lSystemError = mSystemLayer->HandlePlatformTimer(); - lReturn = static_cast(lSystemError); - - exit: - return lReturn; -} - -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -/** - * Prepare the sets of file descriptors for @p select() to work with. - * - * @param[out] nfds The range of file descriptors in the file - * descriptor set. - * - * @param[in] readfds A pointer to the set of readable file descriptors. - * - * @param[in] writefds A pointer to the set of writable file descriptors. - * - * @param[in] exceptfds A pointer to the set of file descriptors with errors. - * - * @param[in] sleepTimeTV A pointer to a structure specifying how long the select should sleep - * - */ -void InetLayer::PrepareSelect(int& nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - struct timeval& sleepTimeTV) -{ - if (State != kState_Initialized) - return; - -#if INET_CONFIG_ENABLE_RAW_ENDPOINT - for (size_t i = 0; i < RawEndPoint::sPool.Size(); i++) - { - RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, nfds, readfds, writefds, exceptfds); - } -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) - { - TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, nfds, readfds, writefds, exceptfds); - } -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - for (size_t i = 0; i < UDPEndPoint::sPool.Size(); i++) - { - UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, nfds, readfds, writefds, exceptfds); - } -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -#if INET_CONFIG_ENABLE_TUN_ENDPOINT - for (size_t i = 0; i < TunEndPoint::sPool.Size(); i++) - { - TunEndPoint* lEndPoint = TunEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, nfds, readfds, writefds, exceptfds); - } -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - if (mSystemLayer == &mImplicitSystemLayer) - { - mSystemLayer->PrepareSelect(nfds, readfds, writefds, exceptfds, sleepTimeTV); - } -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -} - -/** - * Handle I/O from a select call. This method registers the pending I/O - * event in each active endpoint and then invokes the respective I/O - * handling functions for those endpoints. - * - * @note - * It is important to set the pending I/O fields for all endpoints - * *before* making any callbacks. This avoids the case where an - * endpoint is closed and then re-opened within the callback for - * another endpoint. When this happens the new endpoint is likely - * to be assigned the same file descriptor as the old endpoint. - * However, any pending I/O for that file descriptor number represents - * I/O related to the old incarnation of the endpoint, not the current - * one. Saving the pending I/O state in each endpoint before acting - * on it allows the endpoint code to clear the I/O flags in the event - * of a close, thus avoiding any confusion. - * - * @param[in] selectRes The return value of the select call. - * - * @param[in] readfds A pointer to the set of read file descriptors. - * - * @param[in] writefds A pointer to the set of write file descriptors. - * - * @param[in] exceptfds A pointer to the set of file descriptors with - * errors. - * - */ -void InetLayer::HandleSelectResult(int selectRes, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) -{ - if (State != kState_Initialized) - return; - - if (selectRes < 0) - return; - - if (selectRes > 0) - { - // Set the pending I/O field for each active endpoint based on the value returned by select. -#if INET_CONFIG_ENABLE_RAW_ENDPOINT - for (size_t i = 0; i < RawEndPoint::sPool.Size(); i++) - { - RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, readfds, writefds, exceptfds); - } - } -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) - { - TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, readfds, writefds, exceptfds); - } - } -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - for (size_t i = 0; i < UDPEndPoint::sPool.Size(); i++) - { - UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, readfds, writefds, exceptfds); - } - } -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -#if INET_CONFIG_ENABLE_TUN_ENDPOINT - for (size_t i = 0; i < TunEndPoint::sPool.Size(); i++) - { - TunEndPoint* lEndPoint = TunEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, readfds, writefds, exceptfds); - } - } -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT - - // Now call each active endpoint to handle its pending I/O. -#if INET_CONFIG_ENABLE_RAW_ENDPOINT - for (size_t i = 0; i < RawEndPoint::sPool.Size(); i++) - { - RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->HandlePendingIO(); - } - } -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) - { - TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->HandlePendingIO(); - } - } -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - for (size_t i = 0; i < UDPEndPoint::sPool.Size(); i++) - { - UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->HandlePendingIO(); - } - } -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -#if INET_CONFIG_ENABLE_TUN_ENDPOINT - for (size_t i = 0; i < TunEndPoint::sPool.Size(); i++) - { - TunEndPoint* lEndPoint = TunEndPoint::sPool.Get(*mSystemLayer, i); - if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) - { - lEndPoint->HandlePendingIO(); - } - } -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT - } - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - if (mSystemLayer == &mImplicitSystemLayer) - { - mSystemLayer->HandleSelectResult(selectRes, readfds, writefds, exceptfds); - } -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/** - * Reset the members of the IPPacketInfo object. - * - */ -void IPPacketInfo::Clear() -{ - SrcAddress = IPAddress::Any; - DestAddress = IPAddress::Any; - Interface = INET_NULL_INTERFACEID; - SrcPort = 0; - DestPort = 0; -} - - -#if !INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS - -// MARK: InetLayer platform- and system-specific functions for InetLayer -// construction and destruction. - -namespace Platform { -namespace InetLayer { - -/** - * This is a platform-specific InetLayer pre-initialization hook. This - * may be overridden by assserting the preprocessor definition, - * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS. - * - * @param[inout] aLayer A pointer to the InetLayer instance being - * initialized. - * - * @param[inout] aContext Platform-specific context data passed to - * the layer initialization method, ::Init. - * - * @return #INET_NO_ERROR on success; otherwise, a specific error indicating - * the reason for initialization failure. Returning non-successful - * status will abort initialization. - * - */ -DLL_EXPORT INET_ERROR WillInit(Inet::InetLayer *aLayer, void *aContext) -{ - (void)aLayer; - (void)aContext; - - return INET_NO_ERROR; -} - -/** - * This is a platform-specific InetLayer post-initialization hook. This - * may be overridden by assserting the preprocessor definition, - * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS. - * - * @param[inout] aLayer A pointer to the InetLayer instance being - * initialized. - * - * @param[inout] aContext Platform-specific context data passed to - * the layer initialization method, ::Init. - * - * @param[in] anError The overall status being returned via the - * InetLayer ::Init method. - * - */ -DLL_EXPORT void DidInit(Inet::InetLayer *aLayer, void *aContext, INET_ERROR anError) -{ - (void)aLayer; - (void)aContext; - (void)anError; - - return; -} - -/** - * This is a platform-specific InetLayer pre-shutdown hook. This - * may be overridden by assserting the preprocessor definition, - * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS. - * - * @param[inout] aLayer A pointer to the InetLayer instance being - * shutdown. - * - * @param[inout] aContext Platform-specific context data passed to - * the layer initialization method, ::Init. - * - * @return #INET_NO_ERROR on success; otherwise, a specific error indicating - * the reason for shutdown failure. Returning non-successful - * status will abort shutdown. - * - */ -DLL_EXPORT INET_ERROR WillShutdown(Inet::InetLayer *aLayer, void *aContext) -{ - (void)aLayer; - (void)aContext; - - return INET_NO_ERROR; -} - -/** - * This is a platform-specific InetLayer post-shutdown hook. This - * may be overridden by assserting the preprocessor definition, - * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS. - * - * @param[inout] aLayer A pointer to the InetLayer instance being - * shutdown. - * - * @param[inout] aContext Platform-specific context data passed to - * the layer initialization method, ::Init. - * - * @param[in] anError The overall status being returned via the - * InetLayer ::Shutdown method. - * - */ -DLL_EXPORT void DidShutdown(Inet::InetLayer *aLayer, void *aContext, INET_ERROR anError) -{ - (void)aLayer; - (void)aContext; - (void)anError; - - return; -} - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#if CHIP_SYSTEM_CONFIG_USE_LWIP && !INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS -/** - * This is a platform-specific event / message post hook. This may be - * overridden by assserting the preprocessor definition, - * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS. - * - * This posts an event / message of the specified type with the - * provided argument to this instance's platform-specific event / - * message queue. - * - * @note - * This is an implementation for LwIP. - * - * @param[inout] aLayer A pointer to the layer instance to which the - * event / message is being posted. - * - * @param[inout] aContext Platform-specific context data passed to - * the layer initialization method, ::Init. - * - * @param[inout] aTarget A pointer to the InetLayer object making the - * post request. - * - * @param[in] aType The type of event to post. - * - * @param[inout] anArg The argument associated with the event to post. - * - * @return #INET_NO_ERROR on success; otherwise, a specific error indicating - * the reason for initialization failure. - * - */ -INET_ERROR PostEvent(Inet::InetLayer* aInetLayer, void* aContext, InetLayerBasis* aTarget, InetEventType aEventType, - uintptr_t aArgument) -{ - chip::System::Layer& lSystemLayer = *aInetLayer->mSystemLayer; - chip::System::Object& lObject = *aTarget; - chip::System::Error lReturn = chip::System::Platform::Layer::PostEvent(lSystemLayer, aContext, lObject, aEventType, - aArgument); - - return static_cast(lReturn); -} - -/** - * This is a platform-specific event / message dispatch hook. This may - * be overridden by assserting the preprocessor definition, - * INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS. - * - * This effects an event loop, waiting on a queue that services this - * instance, pulling events off of that queue, and then dispatching - * them for handling. - * - * @note - * This is an implementation for LwIP. - * - * @param[inout] aInetLayer A pointer to the layer instance for which - * events / messages are being dispatched. - * - * @param[inout] aContext Platform-specific context data passed to - * the layer initialization method, ::Init. - * - * @retval #INET_ERROR_BAD_ARGS If #aLayer or #aContext is NULL. - * @retval #INET_ERROR_INCORRECT_STATE If the state of the InetLayer - * object is incorrect. - * @retval #INET_ERROR_UNEXPECTED_EVENT If an event type is unrecognized. - * @retval #INET_NO_ERROR On success. - * - */ -INET_ERROR DispatchEvents(Inet::InetLayer* aInetLayer, void* aContext) -{ - chip::System::Layer& lSystemLayer = *aInetLayer->mSystemLayer; - chip::System::Error lReturn = chip::System::Platform::Layer::DispatchEvents(lSystemLayer, aContext); - - return static_cast(lReturn); -} - -/** - * This is a platform-specific event / message dispatch hook. This may - * be overridden by assserting the preprocessor definition, - * INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS. - * - * This dispatches the specified event for handling, unmarshalling the - * type and arguments from the event for hand off to - * InetLayer::HandleEvent for the actual dispatch. - * - * @note - * This is an implementation for LwIP. - * - * @param[inout] aInetLayer A pointer to the layer instance for which - * events / messages are being dispatched. - * - * @param[inout] aContext Platform-specific context data passed to - * the layer initialization method, ::Init. - * - * @param[in] aEvent The platform-specific event object to - * dispatch for handling. - * - * @retval #INET_ERROR_BAD_ARGS If #aLayer or the event target is - * NULL. - * @retval #INET_ERROR_UNEXPECTED_EVENT If the event type is unrecognized. - * @retval #INET_ERROR_INCORRECT_STATE If the state of the InetLayer - * object is incorrect. - * @retval #INET_NO_ERROR On success. - * - */ -INET_ERROR DispatchEvent(Inet::InetLayer* aInetLayer, void* aContext, InetEvent aEvent) -{ - chip::System::Layer& lSystemLayer = *aInetLayer->mSystemLayer; - chip::System::Error lReturn = chip::System::Platform::Layer::DispatchEvent(lSystemLayer, aContext, aEvent); - - return static_cast(lReturn); -} - -/** - * This is a platform-specific event / message dispatch hook. This may be overridden by assserting the preprocessor definition, - * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS. - * - * @note - * This is an implementation for LwIP. - * - * @param[inout] aInetLayer A reference to the layer instance for which events / messages are being dispatched. - * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Init. - * @param[in] aMilliseconds The number of milliseconds to set for the timer. - * - * @retval #INET_NO_ERROR Always succeeds unless overridden. - */ -INET_ERROR StartTimer(Inet::InetLayer* aInetLayer, void* aContext, uint32_t aMilliseconds) -{ - chip::System::Layer& lSystemLayer = *aInetLayer->mSystemLayer; - chip::System::Error lReturn = chip::System::Platform::Layer::StartTimer(lSystemLayer, aContext, aMilliseconds); - - return static_cast(lReturn); -} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP && !INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -} // namespace InetLayer -} // namespace Platform - -#endif // !INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS - -} // namespace Inet -} // namespace chip diff --git a/src/inet/InetLayer.h b/src/inet/InetLayer.h deleted file mode 100644 index fa3d7a301f37c8..00000000000000 --- a/src/inet/InetLayer.h +++ /dev/null @@ -1,457 +0,0 @@ -/* - * - * - * - * 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 or LwIP. - * - * 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. - * - */ - -#ifndef INETLAYER_H -#define INETLAYER_H - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif - -#include - -#include - -#include -#include - -#include - -#include "IANAConstants.h" -#include -#include -#include "IPPrefix.h" -#include -#include "InetLayerBasis.h" -#include - -#if INET_CONFIG_ENABLE_DNS_RESOLVER -#include -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER - -#if INET_CONFIG_ENABLE_RAW_ENDPOINT -#include "RawEndPoint.h" -#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT -#include "TCPEndPoint.h" -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT -#include "UDPEndPoint.h" -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -#if INET_CONFIG_ENABLE_TUN_ENDPOINT -#include "TunEndPoint.h" -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#include "InetBuffer.h" -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#if INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#include "AsyncDNSResolverSockets.h" -#endif // INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if INET_CONFIG_MAX_DROPPABLE_EVENTS - -#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING -#include -#include -#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING - -#if CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING -#include -#include -#endif // CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING - -#endif // INET_CONFIG_MAX_DROPPABLE_EVENTS - -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); - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - extern INET_ERROR PostEvent(Inet::InetLayer *aLayer, void *aContext, InetLayerBasis *aTarget, InetEventType aType, - uintptr_t anArg); - extern INET_ERROR DispatchEvents(Inet::InetLayer *aLayer, void *aContext); - extern INET_ERROR DispatchEvent(Inet::InetLayer *aLayer, void *aContext, InetEvent anEvent); - extern INET_ERROR StartTimer(Inet::InetLayer *aLayer, void *aContext, uint32_t aDurMS); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -} // 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 INET_CONFIG_ENABLE_TUN_ENDPOINT - friend class TunEndPoint; -#endif // INET_CONFIG_ENABLE_TUN_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(void); - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - INET_ERROR Init(void *aContext); -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - - INET_ERROR Init(chip::System::Layer& aSystemLayer, void* aContext); - INET_ERROR Shutdown(void); - - chip::System::Layer* SystemLayer(void) 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 - -#if INET_CONFIG_ENABLE_TUN_ENDPOINT - INET_ERROR NewTunEndPoint(TunEndPoint **retEndPoint); -#endif // INET_CONFIG_ENABLE_TUN_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 INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - /** - * @brief - * This function is the callback to be invoked when a one-shot timer fires. - * - * @param[in] inetLayer A pointer to the InetLayer instance this timer was - * started on. - * - * @param[in] appState A pointer to an application state object registered - * when this timer was started. - * - * @param[in] err #INET_NO_ERROR unconditionally. - */ - typedef void (*TimerCompleteFunct)(InetLayer *inetLayer, void *appState, INET_ERROR err); - INET_ERROR StartTimer(uint32_t durMS, TimerCompleteFunct onComplete, void *appState); - void CancelTimer(TimerCompleteFunct onComplete, void *appState); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - INET_ERROR PostEvent(InetLayerBasis *target, InetEventType type, uintptr_t arg); - INET_ERROR DispatchEvents(void); - INET_ERROR DispatchEvent(InetEvent aEvent); - INET_ERROR HandleEvent(InetLayerBasis &target, InetEventType type, uintptr_t arg); - - // Timer Management - INET_ERROR StartPlatformTimer(uint32_t inDurMS); - INET_ERROR HandlePlatformTimer(void); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - void WakeSelect(void); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -#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); - 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_TUN_ENDPOINT - type == kInetEvent_TunDataReceived || -#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT -#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_PROVIDE_OBSOLESCENT_INTERFACES - chip::System::Layer mImplicitSystemLayer; -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -#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(void); - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#if CHIP_SYSTEM_CONFIG_USE_LWIP - friend INET_ERROR Platform::InetLayer::PostEvent(Inet::InetLayer *aLayer, void *aContext, InetLayerBasis *aTarget, - InetEventType aType, uintptr_t anArg); - friend INET_ERROR Platform::InetLayer::DispatchEvents(Inet::InetLayer *aLayer, void *aContext); - friend INET_ERROR Platform::InetLayer::DispatchEvent(Inet::InetLayer *aLayer, void *aContext, InetEvent anEvent); - friend INET_ERROR Platform::InetLayer::StartTimer(Inet::InetLayer *aLayer, void *aContext, uint32_t aDurMS); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -}; - -inline chip::System::Layer* InetLayer::SystemLayer(void) const -{ - return mSystemLayer; -} - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -inline INET_ERROR InetLayer::Init(void* aContext) -{ - return Init(mImplicitSystemLayer, aContext); -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -inline INET_ERROR InetLayer::DispatchEvent(InetEvent aEvent) -{ - return mSystemLayer->DispatchEvent(aEvent); -} - -inline INET_ERROR InetLayer::HandleEvent(InetLayerBasis& target, InetEventType type, uintptr_t arg) -{ - return mSystemLayer->HandleEvent(target, type, arg); -} -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -inline void InetLayer::WakeSelect(void) -{ - mSystemLayer->WakeSelect(); -} -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -/** - * @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(void); -}; - - -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 - -#endif // !defined(INETLAYER_H) diff --git a/src/inet/InetLayerBasis.cpp b/src/inet/InetLayerBasis.cpp deleted file mode 100644 index 15456958f792ed..00000000000000 --- a/src/inet/InetLayerBasis.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * - * - * 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 contains the basis class for reference counting - * objects by the Inet layer as well as a class for representing - * the pending or resulting I/O events on a socket. - */ - -#include "InetLayerBasis.h" - -namespace chip { -namespace Inet { - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -/** - * Sets the bit for the specified file descriptor in the given sets of file descriptors. - * - * @param[in] socket The file descriptor for which the bit is being set. - * - * @param[out] nfds A reference to the range of file descriptors in the set. - * - * @param[in] readfds A pointer to the set of readable file descriptors. - * - * @param[in] writefds A pointer to the set of writable file descriptors. - * - * @param[in] exceptfds A pointer to the set of file descriptors with errors. - * - */ -void SocketEvents::SetFDs(int socket, int& nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) -{ - if (socket != INET_INVALID_SOCKET_FD) - { - if (IsReadable()) - FD_SET(socket, readfds); - if (IsWriteable()) - FD_SET(socket, writefds); - if (IsError()) - FD_SET(socket, exceptfds); - if (IsSet() && (socket + 1) > nfds) - nfds = socket + 1; - } -} - -/** - * Set the read, write or exception bit flags for the specified socket based on its status in - * the corresponding file descriptor sets. - * - * @param[in] socket The file descriptor for which the bit flags are being set. - * - * @param[in] readfds A pointer to the set of readable file descriptors. - * - * @param[in] writefds A pointer to the set of writable file descriptors. - * - * @param[in] exceptfds A pointer to the set of file descriptors with errors. - * - */ -SocketEvents SocketEvents::FromFDs(int socket, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) -{ - SocketEvents res; - - if (socket != INET_INVALID_SOCKET_FD) - { - if (FD_ISSET(socket, readfds)) - res.SetRead(); - if (FD_ISSET(socket, writefds)) - res.SetWrite(); - if (FD_ISSET(socket, exceptfds)) - res.SetError(); - } - - return res; -} -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -} // namespace Inet -} // namespace chip diff --git a/src/inet/InetLayerBasis.h b/src/inet/InetLayerBasis.h deleted file mode 100644 index ae96daec0e4d83..00000000000000 --- a/src/inet/InetLayerBasis.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * - * - * - * 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 contains the basis class for reference counting - * objects by the Inet layer as well as a class for representing - * the pending or resulting I/O events on a socket. - */ - -#ifndef INETLAYERBASIS_H -#define INETLAYERBASIS_H - -#include - -#include -#include -#include - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include -#endif - -namespace chip { -namespace Inet { - -//--- Forward declaration of InetLayer singleton class -class InetLayer; - -/** - * @class InetLayerBasis - * - * @brief - * This is the basis class of reference-counted objects managed by an - * InetLayer object. - * - */ -class InetLayerBasis : public chip::System::Object -{ -public: - InetLayer& Layer(void) const; - bool IsCreatedByInetLayer(const InetLayer& aInetLayer) const; - -protected: - void InitInetLayerBasis(InetLayer& aInetLayer, void* aAppState = NULL); - -private: - InetLayer* mInetLayer; /**< Pointer to the InetLayer object that owns this object. */ -}; - -/** - * Returns a reference to the Inet layer object that owns this basis object. - */ -inline InetLayer& InetLayerBasis::Layer(void) const -{ - return *mInetLayer; -} - -/** - * Returns \c true if the basis object was obtained by the specified INET layer instance. - * - * @param[in] aInetLayer An instance of the INET layer. - * - * @return \c true if owned by \c aInetLayer, otherwise \c false. - * - * @note - * Does not check whether the object is actually obtained by the system layer instance associated with the INET layer - * instance. It merely tests whether \c aInetLayer is the INET layer instance that was provided to \c InitInetLayerBasis. - */ -inline bool InetLayerBasis::IsCreatedByInetLayer(const InetLayer& aInetLayer) const -{ - return mInetLayer == &aInetLayer; -} - -inline void InetLayerBasis::InitInetLayerBasis(InetLayer& aInetLayer, void* aAppState) -{ - AppState = aAppState; - mInetLayer = &aInetLayer; -} - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -typedef InetLayerBasis InetLayerObject; -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/** - * @class SocketEvents - * - * @brief - * Represent a set of I/O events requested/pending on a socket. - * - */ -class SocketEvents -{ -public: - enum - { - kRead = 0x01, /**< Bit flag indicating if there is a read event on a socket. */ - kWrite = 0x02, /**< Bit flag indicating if there is a write event on a socket. */ - kError = 0x04, /**< Bit flag indicating if there is an error event on a socket. */ - }; - - int Value; /**< Contains the bit flags for the socket event. */ - - /** - * Constructor for the SocketEvents class. - * - */ - SocketEvents() { Value = 0; } - - /** - * Copy constructor for the SocketEvents class. - * - */ - SocketEvents(const SocketEvents& other) { Value = other.Value; } - - /** - * Check if any of the bit flags for the socket events are set. - * - * @return true if set, otherwise false. - * - */ - bool IsSet() const { return Value != 0; } - - /** - * Check if the bit flags indicate that the socket is readable. - * - * @return true if socket is readable, otherwise false. - * - */ - bool IsReadable() const { return (Value & kRead) != 0; } - - /** - * Check if the bit flags indicate that the socket is writable. - * - * @return true if socket is writable, otherwise false. - * - */ - bool IsWriteable() const { return (Value & kWrite) != 0; } - - /** - * Check if the bit flags indicate that the socket has an error. - * - * @return true if socket has an error, otherwise false. - * - */ - bool IsError() const { return (Value & kError) != 0; } - - /** - * Set the read bit flag for the socket. - * - */ - void SetRead() { Value |= kRead; } - - /** - * Set the write bit flag for the socket. - * - */ - void SetWrite() { Value |= kWrite; } - - /** - * Set the error bit flag for the socket. - * - */ - void SetError() { Value |= kError; } - - /** - * Clear the bit flags for the socket. - * - */ - void Clear() { Value = 0; } - - /** - * Clear the read bit flag for the socket. - * - */ - void ClearRead() { Value &= ~kRead; } - - /** - * Clear the write bit flag for the socket. - * - */ - void ClearWrite() { Value &= ~kWrite; } - - /** - * Clear the error bit flag for the socket. - * - */ - void ClearError() { Value &= ~kError; } - - void SetFDs(int socket, int& nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds); - static SocketEvents FromFDs(int socket, fd_set *readfds, fd_set *writefds, fd_set *exceptfds); -}; - -/** - * @def INET_INVALID_SOCKET_FD - * - * @brief - * This is the invalid socket file descriptor identifier. - */ -#define INET_INVALID_SOCKET_FD (-1) - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -} // namespace Inet -} // namespace chip - -#endif // !defined(INETLAYERBASIS_H) diff --git a/src/inet/InetLayerEvents.h b/src/inet/InetLayerEvents.h deleted file mode 100644 index 145c00d91c5d76..00000000000000 --- a/src/inet/InetLayerEvents.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * - * - * 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 enumerates and defines the different types of events - * generated at the Inet layer. - * - */ - -#ifndef INETLAYEREVENTS_H -#define INETLAYEREVENTS_H - -#include - -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -namespace chip { -namespace Inet { - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -/** - * @typedef The basic type for all InetLayer events. - * - * This is defined to a platform- or system-specific type. - * - */ -typedef INET_CONFIG_EVENT_TYPE InetEventType; - -/** - * @typedef The basic object for all InetLayer events. - * - * This is defined to a platform- or system-specific type. - * - */ -typedef INET_CONFIG_EVENT_OBJECT_TYPE InetEvent; -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -/** -* The Inet layer event type definitions. -* -*/ -enum -{ - kInetEvent_TCPConnectComplete = _INET_CONFIG_EVENT(0), /**< The event for TCP connection completion */ - kInetEvent_TCPConnectionReceived = _INET_CONFIG_EVENT(1), /**< The event for TCP connection reception */ - kInetEvent_TCPDataReceived = _INET_CONFIG_EVENT(2), /**< The event for data reception over a TCP connection */ - kInetEvent_TCPDataSent = _INET_CONFIG_EVENT(3), /**< The event for data transmission over a TCP connection */ - kInetEvent_TCPError = _INET_CONFIG_EVENT(4), /**< The event for an error on a TCP connection */ - kInetEvent_UDPDataReceived = _INET_CONFIG_EVENT(5), /**< The event for data reception over UDP */ - kInetEvent_DNSResolveComplete = _INET_CONFIG_EVENT(6), /**< The event for DNS name resolution completion */ - kInetEvent_TunDataReceived = _INET_CONFIG_EVENT(7), /**< The event for data reception over a chip tunnel */ - kInetEvent_RawDataReceived = _INET_CONFIG_EVENT(8) /**< The event for data reception over an InetLayer raw endpoint */ -}; - -/** - * Check to verify if a System::EventType is a valid Inet layer event type. - * - * @param[in] aType A chip System Layer event type. - * - * @return true if it falls within the enumerated range; otherwise, false. - * - */ -static inline bool INET_IsInetEvent(chip::System::EventType aType) -{ - return (aType >= kInetEvent_TCPConnectComplete && - aType <= kInetEvent_RawDataReceived); -} - -} // namespace Inet -} // namespace chip - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#endif // !defined(INETLAYEREVENTS_H) diff --git a/src/inet/InetTimer.cpp b/src/inet/InetTimer.cpp deleted file mode 100644 index 3c38ea2f95fc74..00000000000000 --- a/src/inet/InetTimer.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * - * - * 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 implements InetTimer, a simple wrapper around one-shot - * timer objects. - * - */ - -#include - -#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#include "InetTimer.h" -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES diff --git a/src/inet/InetTimer.h b/src/inet/InetTimer.h deleted file mode 100644 index 795f5ea7e074ec..00000000000000 --- a/src/inet/InetTimer.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * - * - * 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 macros, constants, data structures, and - * functions that represent a wrapper around one-shot timer objects - * - */ - -#ifndef INETTIMER_H -#define INETTIMER_H - -#include - -#if !INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES - -#error "#include // while !INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES." - -#else // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#include - -/** - * Number of nanoseconds in a microsecond - */ - -#define INET_NANOSECONDS_PER_MICROSECOND chip::System::kTimerFactor_nano_per_micro - -/** - * Number of nanoseconds in a millisecond - */ -#define INET_NANOSECONDS_PER_MILLISECOND chip::System::kTimerFactor_nano_per_milli - -/** - * Number of microseconds in a millisecond - */ -#define INET_MICROSECONDS_PER_MILLISECOND chip::System::kTimerFactor_micro_per_milli - -/** - * Number of milliseconds in a second - */ -#define INET_MILLISECONDS_PER_SECOND chip::System::kTimerFactor_milli_per_unit - -/** - * Number of microseconds in a second - */ -#define INET_MICROSECONDS_PER_SECOND chip::System::kTimerFactor_micro_per_unit - -namespace chip { -namespace Inet { - -class InetLayer; - -class InetTimer -{ - friend class InetLayer; - - InetTimer(void); - InetTimer(const InetTimer&); - InetTimer& operator =(const InetTimer&); - -public: - typedef chip::System::Timer::Epoch Time; - - static Time GetTimeMillis(void); - -protected: -}; - -inline InetTimer::Time InetTimer::GetTimeMillis(void) -{ - return chip::System::Timer::GetCurrentEpoch(); -} - -} // namespace Inet -} // namespace chip - -#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES -#endif // !defined(INETTIMER_H) diff --git a/src/inet/InetUtils.cpp b/src/inet/InetUtils.cpp deleted file mode 100644 index 52210c31eb3ced..00000000000000 --- a/src/inet/InetUtils.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * - * - * - * 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 implements methods for parsing host names or IP - * addresses and an optional port number and/or an optional - * interface name from a human-readable string. - * - */ - -#include - -#include - -#include - -namespace chip { -namespace Inet { - -/** - * Parse a human-readable string containing a host or IP address and - * an optional port number (separated by a ':'), supporting the - * following formats: - * - * * - * * : - * * - * * : - * * - * * []: - * - * @param[in] aString The human-reable string to parse. - * - * @param[in] aStringLen The length, in characters, of aString. - * - * @param[out] aHost A pointer to the host name portion of the parsed - * string. - * - * @param[out] aHostLen The length, in characters, of aHost. - * - * @param[out] aPort The port number, if present and successfully - * parsed; otherwise, 0. - * - * @return #INET_ERROR_INVALID_HOST_NAME If the input to be parsed is of - * zero-length or otherwise - * malformed. - * @return #INET_ERROR_HOST_NAME_TOO_LONG If the host name exceeds 253 - * characters. - * @return #INET_NO_ERROR On success. - * - */ -DLL_EXPORT INET_ERROR ParseHostAndPort(const char *aString, uint16_t aStringLen, const char *&aHost, uint16_t &aHostLen, uint16_t &aPort) -{ - const char *end = aString + aStringLen; - const char *p; - - if (aStringLen == 0) - return INET_ERROR_INVALID_HOST_NAME; - - // If the string starts with a [ then it is a backeted - // host/address, possibly with a port number following it. - - if (*aString == '[') - { - // Search for the end bracket. - p = (const char *)memchr(aString, ']', aStringLen); - if (p == NULL) - return INET_ERROR_INVALID_HOST_NAME; - - // Return the IPv6 address. - aHost = aString + 1; - aHostLen = p - aHost; - - // Skip the end bracket. - p++; - } - - // Otherwise, not a bracketed IPv6 address... - else - { - // Search for a colon. - p = (const char *)memchr(aString, ':', aStringLen); - - // If the string contains no colons, then it is a host name or - // IPv4 address without a port. - // - // If the string contains MULTIPLE colons, then it is an IPv6 - // address without a port. - if (p == NULL || memchr(p + 1, ':', end - p - 1) != NULL) - p = end; - - // Return the host/address portion. - aHost = aString; - aHostLen = p - aString; - } - - // Enforce the DNS limit on the maximum length of a host name. - if (aHostLen > 253) - return INET_ERROR_HOST_NAME_TOO_LONG; - - // If there are more characters after the host name... - if (p < end) - { - // Verify the presence of a colon. - if (*p++ != ':') - return INET_ERROR_INVALID_HOST_NAME; - - // Verify that the port number portion is not too long. - if ((end - p) > 5) - return INET_ERROR_INVALID_HOST_NAME; - - // Parse the port number. - aPort = 0; - for (; p < end; p++) - if (*p >= '0' && *p <= '9') - aPort = (aPort * 10) + (*p - '0'); - else - return INET_ERROR_INVALID_HOST_NAME; - } - - // Otherwise, tell the caller there was no port number. - else - aPort = 0; - - return INET_NO_ERROR; -} - -/** - * Parse a human-readable string containing a host or IP address, an - * optional port number (separated by a ':'), and an optional - * interface name (separated by a '%'), supporting the following - * formats: - * - * * - * * % - * * : - * * :% - * * - * * % - * * : - * * :% - * * - * * % - * * []: - * * []:% - * - * @param[in] aString The human-reable string to parse. - * - * @param[in] aStringLen The length, in characters, of aString. - * - * @param[out] aHost A pointer to the host name portion of the parsed - * string. - * - * @param[out] aHostLen The length, in characters, of aHost. - * - * @param[out] aPort The port number, if present and successfully - * parsed; otherwise, 0. - * - * @param[out] aInterface A pointer to the interface portion of the parsed - * string. - * - * @param[out] aInterfaceLen The length, in characters, of aInterface. - * - * @return #INET_ERROR_INVALID_HOST_NAME If the input to be parsed is of - * zero-length or otherwise - * malformed. - * @return #INET_ERROR_HOST_NAME_TOO_LONG If the host name exceeds 253 - * characters. - * @return #INET_NO_ERROR On success. - * - */ -DLL_EXPORT INET_ERROR ParseHostPortAndInterface(const char *aString, uint16_t aStringLen, - const char *&aHost, uint16_t &aHostLen, - uint16_t &aPort, - const char *&aInterface, uint16_t &aInterfaceLen) -{ - const char *end = aString + aStringLen; - - aInterface = NULL; - aInterfaceLen = 0; - - for (uint16_t i = 1; i < aStringLen; i++) - { - char ch = *(end - i); - if (ch == '%') - { - aInterface = end - i + 1; - aInterfaceLen = i - 1; - aStringLen -= i; - break; - } - if (ch == ':' || ch == ']') - break; - } - - return ParseHostAndPort(aString, aStringLen, aHost, aHostLen, aPort); -} - -} // namespace Inet -} // namespace chip diff --git a/src/inet/Makefile b/src/inet/Makefile deleted file mode 100644 index 5617d8e7d711ba..00000000000000 --- a/src/inet/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -TOP_DIR = ../.. -Test_Dir = tests - -.PHONY: all clean run_tests - -all: libnet.a run_tests - -include $(TOP_DIR)/.yams/cpp_rules.min - -Module_Includes = \ - -I. \ - -I$(TOP_DIR)/src \ - -I$(TOP_DIR)/src/system \ - -I$(TOP_DIR)/src/include \ - -I$(TOP_DIR)/src/lib/ \ - -I$(TOP_DIR)/src/lib/core \ - -I$(TOP_DIR)/build/config/standalone/ \ - -I$(TOP_DIR)/third_party/nlio/repo/include \ - -I$(TOP_DIR)/third_party/nlassert/repo/include - -Module_Test_Includes = $(Module_Includes) - -CPP_Files = \ - AsyncDNSResolverSockets.cpp \ - IPEndPointBasis.cpp \ - InetLayer.cpp \ - TCPEndPoint.cpp \ - DNSResolver.cpp \ - IPPrefix.cpp \ - InetLayerBasis.cpp \ - EndPointBasis.cpp \ - InetError.cpp \ - InetTimer.cpp \ - UDPEndPoint.cpp \ - IPAddress-StringFuncts.cpp \ - InetFaultInjection.cpp \ - InetUtils.cpp \ - IPAddress.cpp \ - InetInterface.cpp \ - RawEndPoint.cpp - -libnet.a: $(CPP_Objects) - ar rvs $@ $^ - @echo "LINK => $@" - -clean: my_clean - @rm -f libnet.a *.gcda *.gcno *.gcov diff --git a/src/inet/RawEndPoint.cpp b/src/inet/RawEndPoint.cpp deleted file mode 100644 index 10c8c097eeeb88..00000000000000 --- a/src/inet/RawEndPoint.cpp +++ /dev/null @@ -1,1135 +0,0 @@ -/* - * - * - * - * 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 implements the Inet::RawEndPoint class, - * where the Nest Inet Layer encapsulates methods for interacting - * interacting with IP network endpoints (SOCK_RAW sockets - * on Linux and BSD-derived systems) or LwIP raw protocol - * control blocks, as the system is configured accordingly. - * - */ - -#define __APPLE_USE_RFC_3542 - -#include - -#include "RawEndPoint.h" -#include -#include "InetFaultInjection.h" -#include - -#include -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include -#if HAVE_SYS_SOCKET_H -#include -#endif // HAVE_SYS_SOCKET_H -#include -#include -#include -#include -#if HAVE_NETINET_ICMP6_H -#include -#endif // HAVE_NETINET_ICMP6_H -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -// SOCK_CLOEXEC not defined on all platforms, e.g. iOS/MacOS: -#ifdef SOCK_CLOEXEC -#define SOCK_FLAGS SOCK_CLOEXEC -#else -#define SOCK_FLAGS 0 -#endif - -namespace chip { -namespace Inet { - -using chip::System::PacketBuffer; - -chip::System::ObjectPool RawEndPoint::sPool; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -/* - * Note that for LwIP InterfaceId is already defined to be 'struct - * netif'; consequently, some of the checking performed here could - * conceivably be optimized out and the HAVE_LWIP_UDP_BIND_NETIF case - * could simply be: - * - * udp_bind_netif(aUDP, intfId); - * - */ -static INET_ERROR LwIPBindInterface(struct raw_pcb *aRaw, InterfaceId intfId) -{ - INET_ERROR res = INET_NO_ERROR; - -#if HAVE_LWIP_RAW_BIND_NETIF - if (!IsInterfaceIdPresent(intfId)) - raw_bind_netif(aRaw, NULL); - else - { - struct netif *netifp = IPEndPointBasis::FindNetifFromInterfaceId(intfId); - - if (netifp == NULL) - res = INET_ERROR_UNKNOWN_INTERFACE; - else - raw_bind_netif(aRaw, netifp); - } -#else - if (!IsInterfaceIdPresent(intfId)) - aRaw->intf_filter = NULL; - else - { - struct netif *netifp = IPEndPointBasis::FindNetifFromInterfaceId(intfId); - - if (netifp == NULL) - res = INET_ERROR_UNKNOWN_INTERFACE; - else - aRaw->intf_filter = netifp; - } -#endif // HAVE_LWIP_RAW_BIND_NETIF - - return res; -} -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -/** - * @brief Bind the endpoint to an interface IP address. - * - * @param[in] addrType the protocol version of the IP address - * @param[in] addr the IP address (must be an interface address) - * @param[in] intfId an optional network interface indicator - * - * @retval INET_NO_ERROR success: endpoint bound to address - * @retval INET_ERROR_INCORRECT_STATE endpoint has been bound previously - * @retval INET_NO_MEMORY insufficient memory for endpoint - * - * @retval INET_ERROR_UNKNOWN_INTERFACE - * On some platforms, the optionally specified interface is not - * present. - * - * @retval INET_ERROR_WRONG_PROTOCOL_TYPE - * \c addrType does not match \c IPVer. - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * \c addrType is \c kIPAddressType_Any, or the type of \c addr is not - * equal to \c addrType. - * - * @retval other another system or platform error - * - * @details - * Binds the endpoint to the specified network interface IP address. - * - * On LwIP, this method must not be called with the LwIP stack lock - * already acquired. - */ -INET_ERROR RawEndPoint::Bind(IPAddressType addrType, IPAddress addr, InterfaceId intfId) -{ - INET_ERROR res = INET_NO_ERROR; - - if (mState != kState_Ready && mState != kState_Bound) - { - res = INET_ERROR_INCORRECT_STATE; - goto exit; - } - - if ((addr != IPAddress::Any) && (addr.Type() != kIPAddressType_Any) && (addr.Type() != addrType)) - { - res = INET_ERROR_WRONG_ADDRESS_TYPE; - goto exit; - } - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Make sure we have the appropriate type of PCB. - res = GetPCB(addrType); - - // Bind the PCB to the specified address. - if (res == INET_NO_ERROR) - { -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - ip_addr_t ipAddr = addr.ToLwIPAddr(); -#if INET_CONFIG_ENABLE_IPV4 - lwip_ip_addr_type lType = IPAddress::ToLwIPAddrType(addrType); - IP_SET_TYPE_VAL(ipAddr, lType); -#endif // INET_CONFIG_ENABLE_IPV4 - res = chip::System::MapErrorLwIP(raw_bind(mRaw, &ipAddr)); -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - if (addrType == kIPAddressType_IPv6) - { - ip6_addr_t ipv6Addr = addr.ToIPv6(); - res = chip::System::MapErrorLwIP(raw_bind_ip6(mRaw, &ipv6Addr)); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - { - ip4_addr_t ipv4Addr = addr.ToIPv4(); - res = chip::System::MapErrorLwIP(raw_bind(mRaw, &ipv4Addr)); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - res = INET_ERROR_WRONG_ADDRESS_TYPE; -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - } - - if (res == INET_NO_ERROR) - { - res = LwIPBindInterface(mRaw, intfId); - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - SuccessOrExit(res); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - // Make sure we have the appropriate type of socket. - res = GetSocket(addrType); - SuccessOrExit(res); - - res = IPEndPointBasis::Bind(addrType, addr, 0, intfId); - SuccessOrExit(res); - - mBoundIntfId = intfId; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (res == INET_NO_ERROR) - { - mState = kState_Bound; - } - -exit: - return res; -} - -/** - * Bind the raw endpoint to an IPv6 link-local scope address at the specified - * interface index. Also sets various IPv6 socket options appropriate for - * transmitting packets to and from on-link destinations. - * - * @param[in] intf An InterfaceId to identify the scope of the address. - * - * @param[in] addr An IPv6 link-local scope IPAddress object. - * - * @return INET_NO_ERROR on success, or a mapped OS error on failure. An invalid - * parameter list can result in INET_ERROR_WRONG_ADDRESS_TYPE. If the raw endpoint - * is already bound or is listening, then returns INET_ERROR_INCORRECT_STATE. - */ -/** - * @brief Bind the endpoint to an interface IPv6 link-local address. - * - * @param[in] intf the indicator of the network interface - * @param[in] addr the IP address (must be an interface address) - * - * @retval INET_NO_ERROR success: endpoint bound to address - * @retval INET_ERROR_INCORRECT_STATE endpoint has been bound previously - * @retval INET_NO_MEMORY insufficient memory for endpoint - * - * @retval INET_ERROR_WRONG_PROTOCOL_TYPE - * \c addrType does not match \c IPVer. - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * \c addr is not an IPv6 link-local address or \c intf is - * \c INET_NULL_INTERFACEID. - * - * @retval other another system or platform error - * - * @details - * Binds the endpoint to the IPv6 link-local address \c addr on the - * network interface indicated by \c intf. - * - * On LwIP, this method must not be called with the LwIP stack lock - * already acquired. - */ -INET_ERROR RawEndPoint::BindIPv6LinkLocal(InterfaceId intf, IPAddress addr) -{ - INET_ERROR res = INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - const int lIfIndex = static_cast(intf); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (mState != kState_Ready && mState != kState_Bound) - { - res = INET_ERROR_INCORRECT_STATE; - goto ret; - } - - if (!addr.IsIPv6LinkLocal()) - { - res = INET_ERROR_WRONG_ADDRESS_TYPE; - goto ret; - } - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Make sure we have the appropriate type of PCB. - res = GetPCB(addr.Type()); - - // Bind the PCB to the specified address. - if (res == INET_NO_ERROR) - { -#if LWIP_VERSION_MAJOR > 1 - ip_addr_t ipAddr = addr.ToLwIPAddr(); - res = chip::System::MapErrorLwIP(raw_bind(mRaw, &ipAddr)); -#else // LWIP_VERSION_MAJOR <= 1 - ip6_addr_t ipv6Addr = addr.ToIPv6(); - res = chip::System::MapErrorLwIP(raw_bind_ip6(mRaw, &ipv6Addr)); -#endif // LWIP_VERSION_MAJOR <= 1 - - if (res != INET_NO_ERROR) - { - raw_remove(mRaw); - mRaw = NULL; - mLwIPEndPointType = kLwIPEndPointType_Unknown; - } - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - static const int sInt255 = 255; - - // Make sure we have the appropriate type of socket. - res = GetSocket(kIPAddressType_IPv6); - if (res != INET_NO_ERROR) - { - goto ret; - } - - if (::setsockopt(mSocket, IPPROTO_IPV6, IPV6_MULTICAST_IF, &lIfIndex, sizeof(lIfIndex)) != 0) - { - goto optfail; - } - - if (::setsockopt(mSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &sInt255, sizeof(sInt255)) != 0) - { - goto optfail; - } - - if (::setsockopt(mSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &sInt255, sizeof(sInt255)) != 0) - { - goto optfail; - } - - mAddrType = kIPAddressType_IPv6; - goto ret; - -optfail: - res = chip::System::MapErrorPOSIX(errno); - ::close(mSocket); - mSocket = INET_INVALID_SOCKET_FD; - mAddrType = kIPAddressType_Unknown; - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -ret: - if (res == INET_NO_ERROR) - { - mState = kState_Bound; - } - - return res; -} - -/** - * @brief Prepare the endpoint to receive ICMP messages. - * - * @retval INET_NO_ERROR always returned. - * - * @details - * If \c mState is already \c kState_Listening, then no operation is - * performed, otherwise the \c mState is set to \c kState_Listening and - * the endpoint is prepared to received ICMPv6 messages, according to the - * semantics of the platform. - * - * On LwIP, this method must not be called with the LwIP stack lock - * already acquired - */ -INET_ERROR RawEndPoint::Listen(void) -{ - INET_ERROR res = INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - chip::System::Layer& lSystemLayer = SystemLayer(); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (mState == kState_Listening) - { - res = INET_NO_ERROR; - goto exit; - } - - if (mState != kState_Bound) - { - res = INET_ERROR_INCORRECT_STATE; - goto exit; - } - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - raw_recv(mRaw, LwIPReceiveRawMessage, this); -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - if (PCB_ISIPV6(mRaw)) - raw_recv_ip6(mRaw, LwIPReceiveRawMessage, this); - else - raw_recv(mRaw, LwIPReceiveRawMessage, this); -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - // Wake the thread calling select so that it starts selecting on the new socket. - lSystemLayer.WakeSelect(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (res == INET_NO_ERROR) - { - mState = kState_Listening; - } - - exit: - return res; -} - -/** - * @brief Close the endpoint. - * - * @details - * If mState != kState_Closed, then closes the endpoint, removing - * it from the set of endpoints eligible for communication events. - * - * On LwIP systems, this method must not be called with the LwIP stack - * lock already acquired. - */ -void RawEndPoint::Close(void) -{ - if (mState != kState_Closed) - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Since Raw PCB is released synchronously here, but Raw endpoint itself might have to wait - // for destruction asynchronously, there could be more allocated Raw endpoints than Raw PCBs. - if (mRaw != NULL) - { - raw_remove(mRaw); - mRaw = NULL; - mLwIPEndPointType = kLwIPEndPointType_Unknown; - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (mSocket != INET_INVALID_SOCKET_FD) - { - chip::System::Layer& lSystemLayer = SystemLayer(); - - // Wake the thread calling select so that it recognizes the socket is closed. - lSystemLayer.WakeSelect(); - - close(mSocket); - mSocket = INET_INVALID_SOCKET_FD; - } - - // Clear any results from select() that indicate pending I/O for the socket. - mPendingIO.Clear(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - mState = kState_Closed; - } -} - -/** - * @brief Close the endpoint and recycle its memory. - * - * @details - * Invokes the \c Close method, then invokes the - * InetLayerBasis::Release method to return the object to its - * memory pool. - * - * On LwIP systems, this method must not be called with the LwIP stack - * lock already acquired. - */ -void RawEndPoint::Free(void) -{ - Close(); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - DeferredFree(kReleaseDeferralErrorTactic_Die); -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP - Release(); -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP -} - -/** - * A synonym for SendTo(addr, INET_NULL_INTERFACEID, msg, - * sendFlags). - */ -INET_ERROR RawEndPoint::SendTo(IPAddress addr, chip::System::PacketBuffer *msg, uint16_t sendFlags) -{ - return SendTo(addr, INET_NULL_INTERFACEID, msg, sendFlags); -} - -/** - * @brief Send an ICMP message to the specified destination address. - * - * @param[in] addr the destination IP address - * @param[in] intfId an optional network interface indicator - * @param[in] msg the packet buffer containing the UDP message - * @param[in] sendFlags optional transmit option flags - * - * @retval INET_NO_ERROR - * success: \c msg is queued for transmit. - * - * @retval INET_ERROR_NOT_SUPPORTED - * the system does not support the requested operation. - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * the destination address and the bound interface address do not - * have matching protocol versions or address type. - * - * @retval INET_ERROR_MESSAGE_TOO_LONG - * \c msg does not contain the whole ICMP message. - * - * @retval INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED - * On some platforms, only a truncated portion of \c msg was queued - * for transmit. - * - * @retval other another system or platform error - * - * @details - * Send the ICMP message in \c msg to the destination given in \c addr. - * - * Where (sendFlags & kSendFlag_RetainBuffer) != 0, calls - * chip::System::PacketBuffer::Free on behalf of the caller, otherwise this - * method deep-copies \c msg into a fresh object, and queues that for - * transmission, leaving the original \c msg available after return. - */ -INET_ERROR RawEndPoint::SendTo(IPAddress addr, InterfaceId intfId, chip::System::PacketBuffer *msg, uint16_t sendFlags) -{ - IPPacketInfo pktInfo; - pktInfo.Clear(); - pktInfo.DestAddress = addr; - pktInfo.Interface = intfId; - return SendMsg(&pktInfo, msg, sendFlags); -} - -/** - * @brief Send an ICMP message to the specified destination. - * - * @param[in] pktInfo destination information for the message - * @param[in] msg the packet buffer containing the UDP message - * @param[in] sendFlags optional transmit option flags - * - * @retval INET_NO_ERROR - * success: \c msg is queued for transmit. - * - * @retval INET_ERROR_NOT_SUPPORTED - * the system does not support the requested operation. - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * the destination address and the bound interface address do not - * have matching protocol versions or address type. - * - * @retval INET_ERROR_MESSAGE_TOO_LONG - * \c msg does not contain the whole ICMP message. - * - * @retval INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED - * On some platforms, only a truncated portion of \c msg was queued - * for transmit. - * - * @retval other another system or platform error - * - * @details - * Send the ICMP message \c msg using the destination information given in \c addr. - * - * Where (sendFlags & kSendFlag_RetainBuffer) != 0, calls - * chip::System::PacketBuffer::Free on behalf of the caller, otherwise this - * method deep-copies \c msg into a fresh object, and queues that for - * transmission, leaving the original \c msg available after return. - */ -INET_ERROR RawEndPoint::SendMsg(const IPPacketInfo *pktInfo, chip::System::PacketBuffer *msg, uint16_t sendFlags) -{ - INET_ERROR res = INET_NO_ERROR; - const IPAddress & addr = pktInfo->DestAddress; - - INET_FAULT_INJECT(FaultInjection::kFault_Send, - if ((sendFlags & kSendFlag_RetainBuffer) == 0) - PacketBuffer::Free(msg); - return INET_ERROR_UNKNOWN_INTERFACE; - ); - INET_FAULT_INJECT(FaultInjection::kFault_SendNonCritical, - if ((sendFlags & kSendFlag_RetainBuffer) == 0) - PacketBuffer::Free(msg); - return INET_ERROR_NO_MEMORY; - ); - - // Do not allow sending an IPv4 address on an IPv6 end point and - // vice versa. - - if (IPVer == kIPVersion_6 && addr.Type() != kIPAddressType_IPv6) - { - return INET_ERROR_WRONG_ADDRESS_TYPE; - } -#if INET_CONFIG_ENABLE_IPV4 - else if (IPVer == kIPVersion_4 && addr.Type() != kIPAddressType_IPv4) - { - return INET_ERROR_WRONG_ADDRESS_TYPE; - } -#endif // INET_CONFIG_ENABLE_IPV4 - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - if (sendFlags & kSendFlag_RetainBuffer) - { - // when retaining a buffer, the caller expects the msg to be - // unmodified. LwIP stack will normally prepend the packet - // headers as the packet traverses the IP/netif layers, - // which normally modifies the packet. We prepend a small - // pbuf to the beginning of the pbuf chain, s.t. all headers - // are added to the temporary space, just large enough to hold - // the transport headers. Careful reader will note: - // - // * we're actually oversizing the reserved space, the - // transport header is large enough for the TCP header which - // is larger than the UDP header, but it seemed cleaner than - // the combination of PBUF_IP for reserve space, UDP_HLEN - // for payload, and post allocation adjustment of the header - // space). - // - // * the code deviates from the existing PacketBuffer - // abstractions and needs to reach into the underlying pbuf - // code. The code in PacketBuffer also forces us to perform - // (effectively) a reinterpret_cast rather than a - // static_cast. JIRA WEAV-811 is filed to track the - // re-architecting of the memory management. - - pbuf *msgCopy = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM); - - if (msgCopy == NULL) - { - return INET_ERROR_NO_MEMORY; - } - - pbuf_chain(msgCopy, (pbuf *) msg); - msg = (PacketBuffer *)msgCopy; - } - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Make sure we have the appropriate type of PCB based on the destination address. - res = GetPCB(addr.Type()); - SuccessOrExit(res); - - // Send the message to the specified address/port. - { - err_t lwipErr = ERR_VAL; - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - ip_addr_t ipAddr = addr.ToLwIPAddr(); - - lwipErr = raw_sendto(mRaw, (pbuf *)msg, &ipAddr); -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - if (PCB_ISIPV6(mRaw)) - { - ip6_addr_t ipv6Addr = addr.ToIPv6(); - - lwipErr = raw_sendto_ip6(mRaw, (pbuf *)msg, &ipv6Addr); - } -#if INET_CONFIG_ENABLE_IPV4 - else - { - ip4_addr_t ipv4Addr = addr.ToIPv4(); - - lwipErr = raw_sendto(mRaw, (pbuf *)msg, &ipv4Addr); - } -#endif // INET_CONFIG_ENABLE_IPV4 -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - - if (lwipErr != ERR_OK) - res = chip::System::MapErrorLwIP(lwipErr); - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - PacketBuffer::Free(msg); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - // Make sure we have the appropriate type of socket based on the - // destination address. - - res = GetSocket(addr.Type()); - SuccessOrExit(res); - - res = IPEndPointBasis::SendMsg(pktInfo, msg, sendFlags); - - if ((sendFlags & kSendFlag_RetainBuffer) == 0) - PacketBuffer::Free(msg); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -exit: - CHIP_SYSTEM_FAULT_INJECT_ASYNC_EVENT(); - - return res; -} - -/** - * @brief Set the ICMP6 filter parameters in the network stack. - * - * @param[in] numICMPTypes length of array at \c aICMPTypes - * @param[in] aICMPTypes the set of ICMPv6 type codes to filter. - * - * @retval INET_NO_ERROR success: filter parameters set - * @retval INET_ERROR_NOT_IMPLEMENTED system does not implement - * @retval INET_ERROR_WRONG_ADDRESS_TYPE endpoint not IPv6 type - * @retval INET_ERROR_WRONG_PROTOCOL_TYPE endpoint not ICMP6 type - * - * @retval other another system or platform error - * - * @details - * Apply the ICMPv6 filtering parameters for the codes in \c aICMPTypes to - * the underlying endpoint in the system networking stack. - */ -INET_ERROR RawEndPoint::SetICMPFilter(uint8_t numICMPTypes, const uint8_t * aICMPTypes) -{ - INET_ERROR err; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#if !(HAVE_NETINET_ICMP6_H && HAVE_ICMP6_FILTER) - err = INET_ERROR_NOT_IMPLEMENTED; - ExitNow(); -#endif //!(HAVE_NETINET_ICMP6_H && HAVE_ICMP6_FILTER) -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - VerifyOrExit(IPVer == kIPVersion_6, err = INET_ERROR_WRONG_ADDRESS_TYPE); - VerifyOrExit(IPProto == kIPProtocol_ICMPv6, err = INET_ERROR_WRONG_PROTOCOL_TYPE); - VerifyOrExit((numICMPTypes == 0 && aICMPTypes == NULL) || (numICMPTypes != 0 && aICMPTypes != NULL), err = - INET_ERROR_BAD_ARGS); - - err = INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - LOCK_TCPIP_CORE(); - NumICMPTypes = numICMPTypes; - ICMPTypes = aICMPTypes; - UNLOCK_TCPIP_CORE(); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#if HAVE_NETINET_ICMP6_H && HAVE_ICMP6_FILTER - struct icmp6_filter filter; - if (numICMPTypes > 0) - { - ICMP6_FILTER_SETBLOCKALL(&filter); - for (int j = 0; j < numICMPTypes; ++j) - { - ICMP6_FILTER_SETPASS(aICMPTypes[j], &filter); - } - } - else - { - ICMP6_FILTER_SETPASSALL(&filter); - } - if (setsockopt(mSocket, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) == -1) - { - err = chip::System::MapErrorPOSIX(errno); - } -#endif // HAVE_NETINET_ICMP6_H && HAVE_ICMP6_FILTER -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -exit: - return err; -} - -/** - * @brief Bind the endpoint to a network interface. - * - * @param[in] addrType the protocol version of the IP address. - * - * @param[in] intf indicator of the network interface. - * - * @retval INET_NO_ERROR success: endpoint bound to address - * @retval INET_NO_MEMORY insufficient memory for endpoint - * @retval INET_ERROR_NOT_IMPLEMENTED system implementation not complete. - * - * @retval INET_ERROR_UNKNOWN_INTERFACE - * On some platforms, the interface is not present. - * - * @retval other another system or platform error - * - * @details - * Binds the endpoint to the specified network interface IP address. - * - * On LwIP, this method must not be called with the LwIP stack lock - * already acquired. - */ -INET_ERROR RawEndPoint::BindInterface(IPAddressType addrType, InterfaceId intfId) -{ - INET_ERROR err = INET_NO_ERROR; - - //A lock is required because the LwIP thread may be referring to intf_filter, - //while this code running in the Inet application is potentially modifying it. - //NOTE: this only supports LwIP interfaces whose number is no bigger than 9. - - if (mState != kState_Ready && mState != kState_Bound) - return INET_ERROR_INCORRECT_STATE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - LOCK_TCPIP_CORE(); - - // Make sure we have the appropriate type of PCB. - err = GetPCB(addrType); - SuccessOrExit(err); - - err = LwIPBindInterface(mRaw, intfId); - - UNLOCK_TCPIP_CORE(); - - SuccessOrExit(err); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - // Make sure we have the appropriate type of socket. - err = GetSocket(addrType); - SuccessOrExit(err); - - err = IPEndPointBasis::BindInterface(addrType, intfId); - SuccessOrExit(err); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (err == INET_NO_ERROR) - { - mState = kState_Bound; - } - -exit: - return err; -} - -void RawEndPoint::Init(InetLayer *inetLayer, IPVersion ipVer, IPProtocol ipProto) -{ - IPEndPointBasis::Init(inetLayer); - - IPVer = ipVer; - IPProto = ipProto; -} - -/** - * Get the bound interface on this endpoint. - * - * @return InterfaceId The bound interface id. - */ -InterfaceId RawEndPoint::GetBoundInterface(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if HAVE_LWIP_RAW_BIND_NETIF - return netif_get_by_index(mRaw->netif_idx); -#else - return mRaw->intf_filter; -#endif -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return mBoundIntfId; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -void RawEndPoint::HandleDataReceived(PacketBuffer *msg) -{ - IPEndPointBasis::HandleDataReceived(msg); -} - -INET_ERROR RawEndPoint::GetPCB(IPAddressType addrType) -{ - INET_ERROR lRetval = INET_NO_ERROR; - - // IMPORTANT: This method MUST be called with the LwIP stack LOCKED! - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - if (mRaw == NULL) - { - switch (addrType) - { - case kIPAddressType_IPv6: -#if INET_CONFIG_ENABLE_IPV4 - case kIPAddressType_IPv4: -#endif // INET_CONFIG_ENABLE_IPV4 - mRaw = raw_new_ip_type(IPAddress::ToLwIPAddrType(addrType), IPProto); - break; - - default: - lRetval = INET_ERROR_WRONG_ADDRESS_TYPE; - goto exit; - } - - if (mRaw == NULL) - { - chipLogError(Inet, "raw_new_ip_type failed"); - lRetval = INET_ERROR_NO_MEMORY; - goto exit; - } - else - { - mLwIPEndPointType = kLwIPEndPointType_Raw; - } - } - else - { - const lwip_ip_addr_type lLwIPAddrType = static_cast(IP_GET_TYPE(&mRaw->local_ip)); - - switch (lLwIPAddrType) - { - case IPADDR_TYPE_V6: - VerifyOrExit(addrType == kIPAddressType_IPv6, lRetval = INET_ERROR_WRONG_ADDRESS_TYPE); - break; - -#if INET_CONFIG_ENABLE_IPV4 - case IPADDR_TYPE_V4: - VerifyOrExit(addrType == kIPAddressType_IPv4, lRetval = INET_ERROR_WRONG_ADDRESS_TYPE); - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - default: - break; - } - } -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - if (mRaw == NULL) - { - if (IPVer == kIPVersion_6) - { - mRaw = raw_new_ip6(IPProto); - if (mRaw != NULL) - ip_set_option(mRaw, SOF_REUSEADDR); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (IPVer == kIPVersion_4) - { - mRaw = raw_new(IPProto); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - { - lRetval = INET_ERROR_WRONG_ADDRESS_TYPE; - goto exit; - } - - if (mRaw == NULL) - { - chipLogError(Inet, "raw_new failed"); - lRetval = INET_ERROR_NO_MEMORY; - goto exit; - } - else - { - mLwIPEndPointType = kLwIPEndPointType_Raw; - } - } - else - { -#if INET_CONFIG_ENABLE_IPV4 - const IPAddressType pcbType = PCB_ISIPV6(mRaw) ? kIPAddressType_IPv6 : kIPAddressType_IPv4; -#else // !INET_CONFIG_ENABLE_IPV4 - const IPAddressType pcbType = kIPAddressType_IPv6; -#endif // !INET_CONFIG_ENABLE_IPV4 - - if (addrType != pcbType) { - lRetval = INET_ERROR_WRONG_ADDRESS_TYPE; - goto exit; - } - } -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - -exit: - return (lRetval); -} - -/* This function is executed when a raw_pcb is listening and an IP datagram (v4 or v6) is received. - * NOTE: currently ICMPv4 filtering is currently not implemented, but it can easily be added later. - * This fn() may be executed concurrently with SetICMPFilter() - * - this fn() runs in the LwIP thread (and the lock has already been taken) - * - SetICMPFilter() runs in the Inet thread. - */ -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -u8_t RawEndPoint::LwIPReceiveRawMessage(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 -u8_t RawEndPoint::LwIPReceiveRawMessage(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr) -#endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -{ - RawEndPoint* ep = static_cast(arg); - PacketBuffer* buf = reinterpret_cast(static_cast(p)); - chip::System::Layer& lSystemLayer = ep->SystemLayer(); - IPPacketInfo* pktInfo = NULL; - uint8_t enqueue = 1; - - //Filtering based on the saved ICMP6 types (the only protocol currently supported.) - if ((ep->IPVer == kIPVersion_6) && - (ep->IPProto == kIPProtocol_ICMPv6)) - { - if (ep->NumICMPTypes > 0) - { //When no filter is defined, let all ICMPv6 packets pass - //The type is the first 8 bits field of an ICMP (v4 or v6) packet - uint8_t icmp_type = *(buf->Start() + ip_current_header_tot_len()); - uint8_t icmp_type_found = 0; - for (int j = 0; j < ep->NumICMPTypes; ++j) - { - if (ep->ICMPTypes[j] == icmp_type) - { - icmp_type_found = 1; - break; - } - } - if ( !icmp_type_found ) - { - enqueue = 0; //do not eat it - } - } - } - - if (enqueue) - { - pktInfo = GetPacketInfo(buf); - - if (pktInfo != NULL) - { -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - pktInfo->SrcAddress = IPAddress::FromLwIPAddr(*addr); - pktInfo->DestAddress = IPAddress::FromLwIPAddr(*ip_current_dest_addr()); -#else // LWIP_VERSION_MAJOR <= 1 - if (PCB_ISIPV6(pcb)) - { - pktInfo->SrcAddress = IPAddress::FromIPv6(*(ip6_addr_t *)addr); - pktInfo->DestAddress = IPAddress::FromIPv6(*ip6_current_dest_addr()); - } -#if INET_CONFIG_ENABLE_IPV4 - else - { - pktInfo->SrcAddress = IPAddress::FromIPv4(*addr); - pktInfo->DestAddress = IPAddress::FromIPv4(*ip_current_dest_addr()); - } -#endif // INET_CONFIG_ENABLE_IPV4 -#endif // LWIP_VERSION_MAJOR <= 1 - - pktInfo->Interface = ip_current_netif(); - pktInfo->SrcPort = 0; - pktInfo->DestPort = 0; - } - - if (lSystemLayer.PostEvent(*ep, kInetEvent_RawDataReceived, (uintptr_t)buf) != INET_NO_ERROR) - PacketBuffer::Free(buf); - } - - return enqueue; -} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -INET_ERROR RawEndPoint::GetSocket(IPAddressType aAddressType) -{ - INET_ERROR lRetval = INET_NO_ERROR; - const int lType = (SOCK_RAW | SOCK_FLAGS); - int lProtocol; - - switch (aAddressType) - { - case kIPAddressType_IPv6: - lProtocol = IPPROTO_ICMPV6; - break; - -#if INET_CONFIG_ENABLE_IPV4 - case kIPAddressType_IPv4: - lProtocol = IPPROTO_ICMP; - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - default: - lRetval = INET_ERROR_WRONG_ADDRESS_TYPE; - goto exit; - } - - lRetval = IPEndPointBasis::GetSocket(aAddressType, lType, lProtocol); - SuccessOrExit(lRetval); - -exit: - return (lRetval); -} - -SocketEvents RawEndPoint::PrepareIO(void) -{ - return (IPEndPointBasis::PrepareIO()); -} - -void RawEndPoint::HandlePendingIO(void) -{ - if (mState == kState_Listening && OnMessageReceived != NULL && mPendingIO.IsReadable()) - { - const uint16_t lPort = 0; - - IPEndPointBasis::HandlePendingIO(lPort); - } - - mPendingIO.Clear(); -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -} // namespace Inet -} // namespace chip diff --git a/src/inet/RawEndPoint.h b/src/inet/RawEndPoint.h deleted file mode 100644 index 0615b2e8fdba31..00000000000000 --- a/src/inet/RawEndPoint.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * - * - * 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 header file defines the Inet::RawEndPoint - * class, where the Nest Inet Layer encapsulates methods for - * interacting with IP network endpoints (SOCK_RAW sockets - * on Linux and BSD-derived systems) or LwIP raw protocol - * control blocks, as the system is configured accordingly. - */ - -#ifndef RAWENDPOINT_H -#define RAWENDPOINT_H - -#include "IPEndPointBasis.h" -#include - -#include - -namespace chip { -namespace Inet { - -class InetLayer; -class IPPacketInfo; - -/** - * @brief Objects of this class represent raw IP network endpoints. - * - * @details - * Nest Inet Layer encapsulates methods for interacting with IP network - * endpoints (SOCK_RAW sockets on Linux and BSD-derived systems) or LwIP - * raw protocol control blocks, as the system is configured accordingly. - */ -class DLL_EXPORT RawEndPoint : public IPEndPointBasis -{ - friend class InetLayer; - -public: - /** - * @brief Version of the Internet protocol - * - * @details - * While this field is a mutable class variable, it is an invariant of the - * class that it not be modified. - */ - IPVersion IPVer; // This data member is read-only - - /** - * @brief version of the Internet Control Message Protocol (ICMP) - * - * @details - * While this field is a mutable class variable, it is an invariant of the - * class that it not be modified. - */ - IPProtocol IPProto; // This data member is read-only - - INET_ERROR Bind(IPAddressType addrType, IPAddress addr, InterfaceId intfId = INET_NULL_INTERFACEID); - INET_ERROR BindIPv6LinkLocal(InterfaceId intf, IPAddress addr); - INET_ERROR BindInterface(IPAddressType addrType, InterfaceId intf); - InterfaceId GetBoundInterface(void); - INET_ERROR Listen(void); - INET_ERROR SendTo(IPAddress addr, chip::System::PacketBuffer *msg, uint16_t sendFlags = 0); - INET_ERROR SendTo(IPAddress addr, InterfaceId intfId, chip::System::PacketBuffer *msg, uint16_t sendFlags = 0); - INET_ERROR SendMsg(const IPPacketInfo *pktInfo, chip::System::PacketBuffer *msg, uint16_t sendFlags = 0); - INET_ERROR SetICMPFilter(uint8_t numICMPTypes, const uint8_t * aICMPTypes); - void Close(void); - void Free(void); - -private: - RawEndPoint(void); // not defined - RawEndPoint(const RawEndPoint&); // not defined - ~RawEndPoint(void); // not defined - - static chip::System::ObjectPool sPool; - - void Init(InetLayer *inetLayer, IPVersion ipVer, IPProtocol ipProto); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - uint8_t NumICMPTypes; - const uint8_t *ICMPTypes; - - void HandleDataReceived(chip::System::PacketBuffer *msg); - INET_ERROR GetPCB(IPAddressType addrType); - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - static u8_t LwIPReceiveRawMessage(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr); -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - static u8_t LwIPReceiveRawMessage(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr); -#endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - INET_ERROR GetSocket(IPAddressType addrType); - SocketEvents PrepareIO(void); - void HandlePendingIO(void); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -}; - -} // namespace Inet -} // namespace chip - -#endif // !defined(RAWENDPOINT_H) diff --git a/src/inet/TCPEndPoint.cpp b/src/inet/TCPEndPoint.cpp deleted file mode 100644 index 3705abd21dc096..00000000000000 --- a/src/inet/TCPEndPoint.cpp +++ /dev/null @@ -1,2599 +0,0 @@ -/* - * - * - * - * 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 implements the Inet::TCPEndPoint class, - * where the Nest Inet Layer encapsulates methods for interacting - * with TCP transport endpoints (SOCK_DGRAM sockets on Linux and - * BSD-derived systems) or LwIP TCP protocol control blocks, as - * the system is configured accordingly. - * - */ - -#define __APPLE_USE_RFC_3542 - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif - -#include -#include - -#include - -#include "TCPEndPoint.h" -#include -#include "InetFaultInjection.h" - -#include -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include -#include -#include -#include -#include -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#include "arpa-inet-compatibility.h" - -// SOCK_CLOEXEC not defined on all platforms, e.g. iOS/MacOS: -#ifdef SOCK_CLOEXEC -#define SOCK_FLAGS SOCK_CLOEXEC -#else -#define SOCK_FLAGS 0 -#endif - -#if defined(SOL_TCP) -// socket option level for Linux and BSD systems. -#define TCP_SOCKOPT_LEVEL SOL_TCP -#else -// socket option level for MacOS & iOS systems. -#define TCP_SOCKOPT_LEVEL IPPROTO_TCP -#endif - -#if defined(TCP_KEEPIDLE) -// socket option for Linux and BSD systems. -#define TCP_IDLE_INTERVAL_OPT_NAME TCP_KEEPIDLE -#else -// socket option for MacOS & iOS systems. -#define TCP_IDLE_INTERVAL_OPT_NAME TCP_KEEPALIVE -#endif - -/* - * This logic to register a null operation callback with the LwIP TCP/IP task - * ensures that the TCP timer loop is started when a connection is established, - * which is necessary to ensure that initial SYN and SYN-ACK packets are - * retransmitted during the 3-way handshake. - */ -#if CHIP_SYSTEM_CONFIG_USE_LWIP -namespace { - -void nil_tcpip_callback(void * _aContext) -{ } - -err_t start_tcp_timers(void) -{ - return tcpip_callback(nil_tcpip_callback, NULL); -} - -} // anonymous namespace -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -namespace chip { -namespace Inet { - -using chip::System::PacketBuffer; - -chip::System::ObjectPool TCPEndPoint::sPool; - -INET_ERROR TCPEndPoint::Bind(IPAddressType addrType, IPAddress addr, uint16_t port, bool reuseAddr) -{ - INET_ERROR res = INET_NO_ERROR; - - if (State != kState_Ready) - return INET_ERROR_INCORRECT_STATE; - - if (addr != IPAddress::Any && addr.Type() != kIPAddressType_Any && addr.Type() != addrType) - return INET_ERROR_WRONG_ADDRESS_TYPE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Get the appropriate type of PCB. - res = GetPCB(addrType); - - // Bind the PCB to the specified address/port. - if (res == INET_NO_ERROR) - { - if (reuseAddr) - { - ip_set_option(mTCP, SOF_REUSEADDR); - } - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - - ip_addr_t ipAddr; - if (addr != IPAddress::Any) - { - ipAddr = addr.ToLwIPAddr(); - } - else if (addrType == kIPAddressType_IPv6) - { - ipAddr = ip6_addr_any; - } -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - { - ipAddr = ip_addr_any; - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - res = INET_ERROR_WRONG_ADDRESS_TYPE; - res = chip::System::MapErrorLwIP(tcp_bind(mTCP, &ipAddr, port)); - -#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - - if (addrType == kIPAddressType_IPv6) - { - ip6_addr_t ipv6Addr = addr.ToIPv6(); - res = chip::System::MapErrorLwIP(tcp_bind_ip6(mTCP, &ipv6Addr, port)); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - { - ip_addr_t ipv4Addr = addr.ToIPv4(); - res = chip::System::MapErrorLwIP(tcp_bind(mTCP, &ipv4Addr, port)); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - res = INET_ERROR_WRONG_ADDRESS_TYPE; - -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - res = GetSocket(addrType); - - if (res == INET_NO_ERROR && reuseAddr) - { - int n = 1; - setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)); - -#ifdef SO_REUSEPORT - // Enable SO_REUSEPORT. This permits coexistence between an - // untargetted chip client and other services that listen on - // a chip port on a specific address (such as a chip client - // with TARGETTED_LISTEN or TCP proxying services). Note that - // one of the costs of this implementation is the - // non-deterministic connection dispatch when multple clients - // listen on the address wih the same degreee of selectivity, - // e.g. two untargetted-listen chip clients, or two - // targetted-listen chip clients with the same node id. - - if (setsockopt(mSocket, SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n)) != 0) - { - chipLogError(Inet, "SO_REUSEPORT: %d", errno); - } -#endif // defined(SO_REUSEPORT) - - } - - if (res == INET_NO_ERROR) - { - if (addrType == kIPAddressType_IPv6) - { - struct sockaddr_in6 sa; - memset(&sa, 0, sizeof(sa)); - sa.sin6_family = AF_INET6; - sa.sin6_port = htons(port); - sa.sin6_flowinfo = 0; - sa.sin6_addr = addr.ToIPv6(); - sa.sin6_scope_id = 0; - - if (bind(mSocket, (const sockaddr *) &sa, (unsigned) sizeof(sa)) != 0) - res = chip::System::MapErrorPOSIX(errno); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - { - struct sockaddr_in sa; - memset(&sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - sa.sin_addr = addr.ToIPv4(); - - if (bind(mSocket, (const sockaddr *) &sa, (unsigned) sizeof(sa)) != 0) - res = chip::System::MapErrorPOSIX(errno); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - res = INET_ERROR_WRONG_ADDRESS_TYPE; - } - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (res == INET_NO_ERROR) - State = kState_Bound; - - return res; -} - -INET_ERROR TCPEndPoint::Listen(uint16_t backlog) -{ - INET_ERROR res = INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - chip::System::Layer& lSystemLayer = SystemLayer(); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (State != kState_Bound) - return INET_ERROR_INCORRECT_STATE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Start listening for incoming connections. - mTCP = tcp_listen(mTCP); - mLwIPEndPointType = kLwIPEndPointType_TCP; - - tcp_arg(mTCP, this); - - tcp_accept(mTCP, LwIPHandleIncomingConnection); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (listen(mSocket, backlog) != 0) - res = chip::System::MapErrorPOSIX(errno); - - // Wake the thread calling select so that it recognizes the new socket. - lSystemLayer.WakeSelect(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (res == INET_NO_ERROR) - { - // Once Listening, bump the reference count. The corresponding call to Release() - // [or on LwIP, DeferredRelease()] will happen in DoClose(). - Retain(); - State = kState_Listening; - } - - return res; -} - -INET_ERROR TCPEndPoint::Connect(IPAddress addr, uint16_t port, InterfaceId intf) -{ - INET_ERROR res = INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - chip::System::Layer& lSystemLayer = SystemLayer(); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (State != kState_Ready && State != kState_Bound) - return INET_ERROR_INCORRECT_STATE; - - IPAddressType addrType = addr.Type(); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // LwIP does not provides an API for initiating a TCP connection via a specific interface. - // As a work-around, if the destination is an IPv6 link-local address, we bind the PCB - // to the link local address associated with the source interface; however this is only - // viable if the endpoint hasn't already been bound. - if (intf != INET_NULL_INTERFACEID) - { - IPAddress intfLLAddr; - InetLayer& lInetLayer = Layer(); - - if (!addr.IsIPv6LinkLocal() || State == kState_Bound) - return INET_ERROR_NOT_IMPLEMENTED; - - res = lInetLayer.GetLinkLocalAddr(intf, &intfLLAddr); - if (res != INET_NO_ERROR) - return res; - - res = Bind(kIPAddressType_IPv6, intfLLAddr, 0, true); - if (res != INET_NO_ERROR) - return res; - } - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - res = GetPCB(addrType); - - if (res == INET_NO_ERROR) - { - tcp_arg(mTCP, this); - tcp_err(mTCP, LwIPHandleError); - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - ip_addr_t lwipAddr = addr.ToLwIPAddr(); - res = chip::System::MapErrorLwIP(tcp_connect(mTCP, &lwipAddr, port, LwIPHandleConnectComplete)); -#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - if (addrType == kIPAddressType_IPv6) - { - ip6_addr_t lwipAddr = addr.ToIPv6(); - res = chip::System::MapErrorLwIP(tcp_connect_ip6(mTCP, &lwipAddr, port, LwIPHandleConnectComplete)); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - { - ip_addr_t lwipAddr = addr.ToIPv4(); - res = chip::System::MapErrorLwIP(tcp_connect(mTCP, &lwipAddr, port, LwIPHandleConnectComplete)); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - res = INET_ERROR_WRONG_ADDRESS_TYPE; -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - - // Ensure that TCP timers are started - if (res == INET_NO_ERROR) - { - res = start_tcp_timers(); - } - - if (res == INET_NO_ERROR) - { - State = kState_Connecting; - Retain(); - } - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - res = GetSocket(addrType); - if (res != INET_NO_ERROR) - return res; - - if (intf == INET_NULL_INTERFACEID) - { - // The behavior when connecting to an IPv6 link-local address without specifying an outbound - // interface is ambiguous. So prevent it in all cases. - if (addr.IsIPv6LinkLocal()) - return INET_ERROR_WRONG_ADDRESS_TYPE; - } - else - { - // Try binding to the interface - - // If destination is link-local then there is no need to bind to - // interface or address on the interface. - - if (!addr.IsIPv6LinkLocal()) - { -#ifdef SO_BINDTODEVICE - struct ::ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - - res = GetInterfaceName(intf, ifr.ifr_name, sizeof(ifr.ifr_name)); - if (res != INET_NO_ERROR) - return res; - - // Attempt to bind to the interface using SO_BINDTODEVICE which requires privileged access. - // If the permission is denied(EACCES) because chip is running in a context - // that does not have privileged access, choose a source address on the - // interface to bind the connetion to. - int r = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)); - if (r < 0 && errno != EACCES) - { - return res = chip::System::MapErrorPOSIX(errno); - } - - if (r < 0) -#endif // SO_BINDTODEVICE - { - // Attempting to initiate a connection via a specific interface is not allowed. - // The only way to do this is to bind the local to an address on the desired - // interface. - res = BindSrcAddrFromIntf(addrType, intf); - if (res != INET_NO_ERROR) - return res; - } - } - } - - // Disable generation of SIGPIPE. -#ifdef SO_NOSIGPIPE - int n = 1; - setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &n, sizeof(n)); -#endif // defined(SO_NOSIGPIPE) - - // Enable non-blocking mode for the socket. - int flags = fcntl(mSocket, F_GETFL, 0); - fcntl(mSocket, F_SETFL, flags | O_NONBLOCK); - - int sockaddrsize = 0; - const sockaddr *sockaddrptr = NULL; - - union - { - sockaddr any; - sockaddr_in6 in6; -#if INET_CONFIG_ENABLE_IPV4 - sockaddr_in in; -#endif // INET_CONFIG_ENABLE_IPV4 - } sa; - memset(&sa, 0, sizeof(sa)); - - if (addrType == kIPAddressType_IPv6) - { - sa.in6.sin6_family = AF_INET6; - sa.in6.sin6_port = htons(port); - sa.in6.sin6_flowinfo = 0; - sa.in6.sin6_addr = addr.ToIPv6(); - sa.in6.sin6_scope_id = intf; - sockaddrsize = sizeof(sockaddr_in6); - sockaddrptr = (const sockaddr *) &sa.in6; - } -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - { - sa.in.sin_family = AF_INET; - sa.in.sin_port = htons(port); - sa.in.sin_addr = addr.ToIPv4(); - sockaddrsize = sizeof(sockaddr_in); - sockaddrptr = (const sockaddr *) &sa.in; - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - return INET_ERROR_WRONG_ADDRESS_TYPE; - - int conRes = connect(mSocket, sockaddrptr, sockaddrsize); - - if (conRes == -1 && errno != EINPROGRESS) - { - res = chip::System::MapErrorPOSIX(errno); - DoClose(res, true); - return res; - } - - // Once Connecting or Connected, bump the reference count. The corresponding Release() - // [or on LwIP, DeferredRelease()] will happen in DoClose(). - Retain(); - - if (conRes == 0) - { - State = kState_Connected; - if (OnConnectComplete != NULL) - OnConnectComplete(this, INET_NO_ERROR); - } - else - State = kState_Connecting; - - // Wake the thread calling select so that it recognizes the new socket. - lSystemLayer.WakeSelect(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - StartConnectTimerIfSet(); - - return res; -} - -/** - * @brief Set timeout for Connect to succeed or return an error. - * - * @param[in] connTimeoutMsecs - * - * @note - * Setting a value of zero means use system defaults. - */ -void TCPEndPoint::SetConnectTimeout(const uint32_t connTimeoutMsecs) -{ - mConnectTimeoutMsecs = connTimeoutMsecs; -} - -void TCPEndPoint::StartConnectTimerIfSet(void) -{ - if (mConnectTimeoutMsecs > 0) - { - chip::System::Layer& lSystemLayer = SystemLayer(); - - lSystemLayer.StartTimer(mConnectTimeoutMsecs, TCPConnectTimeoutHandler, this); - } -} - -void TCPEndPoint::StopConnectTimer(void) -{ - chip::System::Layer& lSystemLayer = SystemLayer(); - - lSystemLayer.CancelTimer(TCPConnectTimeoutHandler, this); -} - -void TCPEndPoint::TCPConnectTimeoutHandler(chip::System::Layer* aSystemLayer, void* aAppState, chip::System::Error aError) -{ - TCPEndPoint * tcpEndPoint = reinterpret_cast(aAppState); - - VerifyOrDie((aSystemLayer != NULL) && (tcpEndPoint != NULL)); - - // Close Connection as we have timed out and Connect has not returned to - // stop this timer. - tcpEndPoint->DoClose(INET_ERROR_TCP_CONNECT_TIMEOUT, false); -} - -INET_ERROR TCPEndPoint::GetPeerInfo(IPAddress *retAddr, uint16_t *retPort) const -{ - INET_ERROR res = INET_NO_ERROR; - - if (!IsConnected()) - return INET_ERROR_INCORRECT_STATE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - if (mTCP != NULL) - { - *retPort = mTCP->remote_port; - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - *retAddr = IPAddress::FromLwIPAddr(mTCP->remote_ip); -#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 -#if INET_CONFIG_ENABLE_IPV4 - *retAddr = PCB_ISIPV6(mTCP) ? IPAddress::FromIPv6(mTCP->remote_ip.ip6) : IPAddress::FromIPv4(mTCP->remote_ip.ip4); -#else // !INET_CONFIG_ENABLE_IPV4 - *retAddr = IPAddress::FromIPv6(mTCP->remote_ip.ip6); -#endif // !INET_CONFIG_ENABLE_IPV4 -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - } - else - res = INET_ERROR_CONNECTION_ABORTED; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - union - { - sockaddr any; - sockaddr_in in; - sockaddr_in6 in6; - } sa; - memset(&sa, 0, sizeof(sa)); - socklen_t saLen = sizeof(sa); - - if (getpeername(mSocket, &sa.any, &saLen) != 0) - return chip::System::MapErrorPOSIX(errno); - - if (sa.any.sa_family == AF_INET6) - { - *retAddr = IPAddress::FromIPv6(sa.in6.sin6_addr); - *retPort = ntohs(sa.in6.sin6_port); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (sa.any.sa_family == AF_INET) - { - *retAddr = IPAddress::FromIPv4(sa.in.sin_addr); - *retPort = ntohs(sa.in.sin_port); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - return INET_ERROR_INCORRECT_STATE; - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return res; -} - -INET_ERROR TCPEndPoint::GetLocalInfo(IPAddress *retAddr, uint16_t *retPort) -{ - INET_ERROR res = INET_NO_ERROR; - - if (!IsConnected()) - return INET_ERROR_INCORRECT_STATE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - if (mTCP != NULL) - { - *retPort = mTCP->local_port; - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - *retAddr = IPAddress::FromLwIPAddr(mTCP->local_ip); -#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 -#if INET_CONFIG_ENABLE_IPV4 - *retAddr = PCB_ISIPV6(mTCP) ? IPAddress::FromIPv6(mTCP->local_ip.ip6) : IPAddress::FromIPv4(mTCP->local_ip.ip4); -#else // !INET_CONFIG_ENABLE_IPV4 - *retAddr = IPAddress::FromIPv6(mTCP->local_ip.ip6); -#endif // !INET_CONFIG_ENABLE_IPV4 -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - } - else - res = INET_ERROR_CONNECTION_ABORTED; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - union - { - sockaddr any; - sockaddr_in6 in6; -#if INET_CONFIG_ENABLE_IPV4 - sockaddr_in in; -#endif // INET_CONFIG_ENABLE_IPV4 - } sa; - - memset(&sa, 0, sizeof(sa)); - socklen_t saLen = sizeof(sa); - - if (getsockname(mSocket, &sa.any, &saLen) != 0) - return chip::System::MapErrorPOSIX(errno); - - if (sa.any.sa_family == AF_INET6) - { - *retAddr = IPAddress::FromIPv6(sa.in6.sin6_addr); - *retPort = ntohs(sa.in6.sin6_port); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (sa.any.sa_family == AF_INET) - { - *retAddr = IPAddress::FromIPv4(sa.in.sin_addr); - *retPort = ntohs(sa.in.sin_port); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - return INET_ERROR_INCORRECT_STATE; - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return res; -} - -INET_ERROR TCPEndPoint::Send(PacketBuffer *data, bool push) -{ - INET_ERROR res = INET_NO_ERROR; - - if (State != kState_Connected && State != kState_ReceiveShutdown) - { - PacketBuffer::Free(data); - return INET_ERROR_INCORRECT_STATE; - } - - if (mSendQueue == NULL) - mSendQueue = data; - else - mSendQueue->AddToEnd(data); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - if (mUnsentQueue == NULL) - { - mUnsentQueue = data; - mUnsentOffset = 0; - } - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - if (!mUserTimeoutTimerRunning) - { - // Timer was not running before this send. So, start - // the timer. - - StartTCPUserTimeoutTimer(); - } -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - - if (push) - res = DriveSending(); - - return res; -} - -void TCPEndPoint::DisableReceive() -{ - ReceiveEnabled = false; -} - -void TCPEndPoint::EnableReceive() -{ -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - chip::System::Layer& lSystemLayer = SystemLayer(); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - ReceiveEnabled = true; - - DriveReceiving(); - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - // Wake the thread calling select so that it can include the socket - // in the select read fd_set. - lSystemLayer.WakeSelect(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -} - -/** - * TCPEndPoint::EnableNoDelay - * - * @brief - * Switch off nagle buffering algorithm in TCP by setting the - * TCP_NODELAY socket options. - * - */ - -INET_ERROR TCPEndPoint::EnableNoDelay(void) -{ - INET_ERROR res = INET_NO_ERROR; - - if (!IsConnected()) - return INET_ERROR_INCORRECT_STATE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - if (mTCP != NULL) - tcp_nagle_disable(mTCP); - else - res = INET_ERROR_CONNECTION_ABORTED; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - { - int val; - -#ifdef TCP_NODELAY - // Disable TCP Nagle buffering by setting TCP_NODELAY socket option to true - val = 1; - if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_NODELAY, &val, sizeof(val)) != 0) - return chip::System::MapErrorPOSIX(errno); -#endif // defined(TCP_NODELAY) - } - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return res; -} - -/** - * TCPEndPoint::EnableKeepAlive - * - * @brief - * Enable TCP keepalive probes on the associated TCP connection. - * - * @param interval - * The interval (in seconds) between keepalive probes. This value also controls - * the time between last data packet sent and the transmission of the first keepalive - * probe. - * - * @param timeoutCount - * The maximum number of unacknowledged probes before the connection will be deemed - * to have failed. - * - * @note - * This method can only be called when the endpoint is in one of the connected states. - * - * This method can be called multiple times to adjust the keepalive interval or timeout - * count. - */ - -INET_ERROR TCPEndPoint::EnableKeepAlive(uint16_t interval, uint16_t timeoutCount) -{ - INET_ERROR res = INET_NO_ERROR; - - if (!IsConnected()) - return INET_ERROR_INCORRECT_STATE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -#if LWIP_TCP_KEEPALIVE - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - if (mTCP != NULL) - { - // Set the idle interval - mTCP->keep_idle = (uint32_t)interval * 1000; - - // Set the probe retransmission interval. - mTCP->keep_intvl = (uint32_t)interval * 1000; - - // Set the probe timeout count - mTCP->keep_cnt = timeoutCount; - - // Enable keepalives for the connection. - ip_set_option(mTCP, SOF_KEEPALIVE); - } - else - res = INET_ERROR_CONNECTION_ABORTED; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#else // LWIP_TCP_KEEPALIVE - - res = INET_ERROR_NOT_IMPLEMENTED; - -#endif // LWIP_TCP_KEEPALIVE - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - { - int val; - - // Set the idle interval - val = interval; - if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_IDLE_INTERVAL_OPT_NAME, &val, sizeof(val)) != 0) - return chip::System::MapErrorPOSIX(errno); - - // Set the probe retransmission interval. - val = interval; - if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_KEEPINTVL, &val, sizeof(val)) != 0) - return chip::System::MapErrorPOSIX(errno); - - // Set the probe timeout count - val = timeoutCount; - if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_KEEPCNT, &val, sizeof(val)) != 0) - return chip::System::MapErrorPOSIX(errno); - - // Enable keepalives for the connection. - val = 1; // enable - if (setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0) - return chip::System::MapErrorPOSIX(errno); - } - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return res; -} - -/** - * TCPEndPoint::DisableKeepAlive - * - * @brief - * Disable TCP keepalive probes on the associated TCP connection. - * - * @note - * This method can only be called when the endpoint is in one of the connected states. - * - * This method does nothing if keepalives have not been enabled on the endpoint. - */ - -INET_ERROR TCPEndPoint::DisableKeepAlive() -{ - INET_ERROR res = INET_NO_ERROR; - - if (!IsConnected()) - return INET_ERROR_INCORRECT_STATE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -#if LWIP_TCP_KEEPALIVE - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - if (mTCP != NULL) - { - // Disable keepalives on the connection. - ip_reset_option(mTCP, SOF_KEEPALIVE); - } - else - res = INET_ERROR_CONNECTION_ABORTED; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#else // LWIP_TCP_KEEPALIVE - - res = INET_ERROR_NOT_IMPLEMENTED; - -#endif // LWIP_TCP_KEEPALIVE - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - { - int val; - - // Disable keepalives on the connection. - val = 0; // disable - if (setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0) - return chip::System::MapErrorPOSIX(errno); - } - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return res; -} - -/** - * TCPEndPoint::SetUserTimeout - * - * @brief Set the TCP user timeout socket option. - * - * @details - * When the value is greater than 0, it specifies the maximum amount of - * time in milliseconds that transmitted data may remain - * unacknowledged before TCP will forcibly close the - * corresponding connection. If the option value is specified as 0, - * TCP will use the system default. - * See RFC 5482, for further details. - * - * @note - * This method can only be called when the endpoint is in one of the connected states. - * - * This method can be called multiple times to adjust the keepalive interval or timeout - * count. - */ -INET_ERROR TCPEndPoint::SetUserTimeout(uint32_t userTimeoutMillis) -{ - INET_ERROR res = INET_NO_ERROR; - - if (!IsConnected()) - { - return INET_ERROR_INCORRECT_STATE; - } - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - - // Store the User timeout configuration if it is being overridden. - - mUserTimeoutMillis = userTimeoutMillis; - -#else // !INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if defined(TCP_USER_TIMEOUT) - // Set the user timeout - uint32_t val = userTimeoutMillis; - if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_USER_TIMEOUT, &val, sizeof(val)) != 0) - return chip::System::MapErrorPOSIX(errno); -#else // TCP_USER_TIMEOUT - res = INET_ERROR_NOT_IMPLEMENTED; -#endif // defined(TCP_USER_TIMEOUT) - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - res = INET_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#endif // !INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - - return res; -} - -INET_ERROR TCPEndPoint::AckReceive(uint16_t len) -{ - INET_ERROR res = INET_NO_ERROR; - - if (!IsConnected()) - return INET_ERROR_INCORRECT_STATE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - if (mTCP != NULL) - tcp_recved(mTCP, len); - else - res = INET_ERROR_CONNECTION_ABORTED; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - // nothing to do for sockets case - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return res; -} - -INET_ERROR TCPEndPoint::PutBackReceivedData(PacketBuffer *data) -{ - if (!IsConnected()) - return INET_ERROR_INCORRECT_STATE; - - mRcvQueue = data; - - return INET_NO_ERROR; -} - -uint32_t TCPEndPoint::PendingSendLength() -{ - if (mSendQueue != NULL) - return mSendQueue->TotalLength(); - else - return 0; -} - -uint32_t TCPEndPoint::PendingReceiveLength() -{ - if (mRcvQueue != NULL) - return mRcvQueue->TotalLength(); - else - return 0; -} - -INET_ERROR TCPEndPoint::Shutdown() -{ - INET_ERROR err = INET_NO_ERROR; - - if (!IsConnected()) - return INET_ERROR_INCORRECT_STATE; - - // If fully connected, enter the SendShutdown state. - if (State == kState_Connected) - { - State = kState_SendShutdown; - DriveSending(); - } - - // Otherwise, if the peer has already closed their end of the connection, - else if (State == kState_ReceiveShutdown) - err = DoClose(err, false); - - return err; -} - -INET_ERROR TCPEndPoint::Close() -{ - // Clear the receive queue. - PacketBuffer::Free(mRcvQueue); - mRcvQueue = NULL; - - // Suppress closing callbacks, since the application explicitly called Close(). - OnConnectionClosed = NULL; - OnPeerClose = NULL; - OnConnectComplete = NULL; - - // Perform a graceful close. - return DoClose(INET_NO_ERROR, true); -} - -void TCPEndPoint::Abort() -{ - // Suppress closing callbacks, since the application explicitly called Abort(). - OnConnectionClosed = NULL; - OnPeerClose = NULL; - OnConnectComplete = NULL; - - DoClose(INET_ERROR_CONNECTION_ABORTED, true); -} - -void TCPEndPoint::Free() -{ - INET_ERROR err; - - // Ensure no callbacks to the app after this point. - OnAcceptError = NULL; - OnConnectComplete = NULL; - OnConnectionReceived = NULL; - OnConnectionClosed = NULL; - OnPeerClose = NULL; - OnDataReceived = NULL; - OnDataSent = NULL; - - // Ensure the end point is Closed or Closing. - err = Close(); - if (err != INET_NO_ERROR) - Abort(); - - // Release the Retain() that happened when the end point was allocated - // [on LwIP, the object may still be alive if DoClose() used the - // EndPointBasis::DeferredFree() method.] - Release(); -} - -#if INET_TCP_IDLE_CHECK_INTERVAL > 0 -void TCPEndPoint::SetIdleTimeout(uint32_t timeoutMS) -{ - uint32_t newIdleTimeout = (timeoutMS + (INET_TCP_IDLE_CHECK_INTERVAL - 1)) / INET_TCP_IDLE_CHECK_INTERVAL; - InetLayer& lInetLayer = Layer(); - bool isIdleTimerRunning = lInetLayer.IsIdleTimerRunning(); - - if (newIdleTimeout > UINT16_MAX) - newIdleTimeout = UINT16_MAX; - mIdleTimeout = mRemainingIdleTime = newIdleTimeout; - - if (!isIdleTimerRunning && mIdleTimeout) - { - chip::System::Layer& lSystemLayer = SystemLayer(); - - lSystemLayer.StartTimer(INET_TCP_IDLE_CHECK_INTERVAL, InetLayer::HandleTCPInactivityTimer, &lInetLayer); - } -} -#endif // INET_TCP_IDLE_CHECK_INTERVAL > 0 - -bool TCPEndPoint::IsConnected(int state) -{ - return state == kState_Connected || state == kState_SendShutdown || state == kState_ReceiveShutdown || state == kState_Closing; -} - -void TCPEndPoint::Init(InetLayer *inetLayer) -{ - InitEndPointBasis(*inetLayer); - ReceiveEnabled = true; - - // Initialize to zero for using system defaults. - mConnectTimeoutMsecs = 0; - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - mUserTimeoutMillis = INET_CONFIG_DEFAULT_TCP_USER_TIMEOUT_MSEC; - - mUserTimeoutTimerRunning = false; - -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - mIsTCPSendIdle = true; - - mTCPSendQueuePollPeriodMillis = INET_CONFIG_TCP_SEND_QUEUE_POLL_INTERVAL_MSEC; - - mTCPSendQueueRemainingPollCount = MaxTCPSendQueuePolls(); - - OnTCPSendIdleChanged = NULL; -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - mBytesWrittenSinceLastProbe = 0; - - mLastTCPKernelSendQueueLen = 0; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT -} - -INET_ERROR TCPEndPoint::DriveSending() -{ - INET_ERROR err = INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // If the connection hasn't been aborted ... - if (mTCP != NULL) - { - err_t lwipErr; - - // Determine the current send window size. This is the maximum amount we can write to the connection. - uint16_t sendWindowSize = tcp_sndbuf(mTCP); - - // If there's data to be sent and the send window is open... - bool canSend = (mUnsentQueue != NULL && sendWindowSize > 0); - if (canSend) - { - // While there's data to be sent and a window to send it in... - do - { - uint16_t bufDataLen = mUnsentQueue->DataLength(); - - // Get a pointer to the start of unsent data within the first buffer on the unsent queue. - uint8_t *sendData = mUnsentQueue->Start() + mUnsentOffset; - - // Determine the amount of data to send from the current buffer. - uint16_t sendLen = bufDataLen - mUnsentOffset; - if (sendLen > sendWindowSize) - sendLen = sendWindowSize; - - // Adjust the unsent data offset by the length of data to be written. If the entire buffer - // has been sent advance to the next one. - mUnsentOffset += sendLen; - if (mUnsentOffset == bufDataLen) - { - mUnsentQueue = mUnsentQueue->Next(); - mUnsentOffset = 0; - } - - // Adjust the remaining window size. - sendWindowSize -= sendLen; - - // Determine if there's more data to be sent after this buffer. - canSend = (mUnsentQueue != NULL && sendWindowSize > 0); - - // Call LwIP to queue the data to be sent, telling it if there's more data to come. - lwipErr = tcp_write(mTCP, sendData, sendLen, (canSend) ? TCP_WRITE_FLAG_MORE : 0); - if (lwipErr != ERR_OK) - { - err = chip::System::MapErrorLwIP(lwipErr); - break; - } - } while (canSend); - - // Call LwIP to send the queued data. - INET_FAULT_INJECT(FaultInjection::kFault_Send, err = chip::System::MapErrorLwIP(ERR_RTE)); - - if (err == INET_NO_ERROR) - { - lwipErr = tcp_output(mTCP); - - if (lwipErr != ERR_OK) - err = chip::System::MapErrorLwIP(lwipErr); - } - } - - if (err == INET_NO_ERROR) - { - // If in the SendShutdown state and the unsent queue is now empty, shutdown the PCB for sending. - if (State == kState_SendShutdown && mUnsentQueue == NULL) - { - lwipErr = tcp_shutdown(mTCP, 0, 1); - if (lwipErr != ERR_OK) - err = chip::System::MapErrorLwIP(lwipErr); - } - } - } - - else - err = INET_ERROR_CONNECTION_ABORTED; - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#ifdef MSG_NOSIGNAL - const int sendFlags = MSG_NOSIGNAL; -#else - const int sendFlags = 0; -#endif - - // Pretend send() fails in the while loop below - INET_FAULT_INJECT(FaultInjection::kFault_Send, - { - err = chip::System::MapErrorPOSIX(EIO); - DoClose(err, false); - return err; - }); - - while (mSendQueue != NULL) - { - uint16_t bufLen = mSendQueue->DataLength(); - - ssize_t lenSent = send(mSocket, mSendQueue->Start(), (size_t) bufLen, sendFlags); - - if (lenSent == -1) - { - if (errno != EAGAIN && errno != EWOULDBLOCK) - err = (errno == EPIPE) ? INET_ERROR_PEER_DISCONNECTED : chip::System::MapErrorPOSIX(errno); - break; - } - - // Mark the connection as being active. - MarkActive(); - - if (lenSent < bufLen) - mSendQueue->ConsumeHead(lenSent); - else - mSendQueue = PacketBuffer::FreeHead(mSendQueue); - - if (OnDataSent != NULL) - OnDataSent(this, (uint16_t) lenSent); - -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - // TCP Send is not Idle; Set state and notify if needed - - SetTCPSendIdleAndNotifyChange(false); -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - mBytesWrittenSinceLastProbe += lenSent; - - bool isProgressing = false; - - err = CheckConnectionProgress(isProgressing); - if (err != INET_NO_ERROR) - { - break; - } - - if (!mUserTimeoutTimerRunning) - { - // Timer was not running before this write. So, start - // the timer. - - StartTCPUserTimeoutTimer(); - } - else if (isProgressing) - { - // Progress is being made. So, shift the timer - // forward if it was started. - - RestartTCPUserTimeoutTimer(); - } -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - - if (lenSent < bufLen) - break; - } - - if (err == INET_NO_ERROR) - { - // If we're in the SendShutdown state and the send queue is now empty, shutdown writing on the socket. - if (State == kState_SendShutdown && mSendQueue == NULL) - { - if (shutdown(mSocket, SHUT_WR) != 0) - err = chip::System::MapErrorPOSIX(errno); - } - } - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (err != INET_NO_ERROR) - DoClose(err, false); - - CHIP_SYSTEM_FAULT_INJECT_ASYNC_EVENT(); - - return err; -} - -void TCPEndPoint::DriveReceiving() -{ - // If there's data in the receive queue and the app is ready to receive it then call the app's callback - // with the entire receive queue. - if (mRcvQueue != NULL && ReceiveEnabled && OnDataReceived != NULL) - { - PacketBuffer *rcvQueue = mRcvQueue; - mRcvQueue = NULL; - OnDataReceived(this, rcvQueue); - } - - // If the connection is closing, and the receive queue is now empty, call DoClose() to complete - // the process of closing the connection. - if (State == kState_Closing && mRcvQueue == NULL) - DoClose(INET_NO_ERROR, false); -} - -void TCPEndPoint::HandleConnectComplete(INET_ERROR err) -{ - // If the connect succeeded enter the Connected state and call the app's callback. - if (err == INET_NO_ERROR) - { - // Stop the TCP Connect timer in case it is still running. - StopConnectTimer(); - - // Mark the connection as being active. - MarkActive(); - - State = kState_Connected; - if (OnConnectComplete != NULL) - OnConnectComplete(this, INET_NO_ERROR); - } - - // Otherwise, close the connection with an error. - else - DoClose(err, false); -} - -INET_ERROR TCPEndPoint::DoClose(INET_ERROR err, bool suppressCallback) -{ - int oldState = State; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - struct linger lingerStruct; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - // If in one of the connected states (Connected, LocalShutdown, PeerShutdown or Closing) - // AND this is a graceful close (i.e. not prompted by an error) - // AND there is data waiting to be processed on either the send or receive queues - // ... THEN enter the Closing state, allowing the queued data to drain, - // ... OTHERWISE go straight to the Closed state. - if (IsConnected() && err == INET_NO_ERROR && (mSendQueue != NULL || mRcvQueue != NULL)) - State = kState_Closing; - else - State = kState_Closed; - - // Stop the Connect timer in case it is still running. - - StopConnectTimer(); - - // If not making a state transition, return immediately. - if (State == oldState) - return INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // If the LwIP PCB hasn't been closed yet... - if (mTCP != NULL) - { - // If the endpoint was a connection endpoint (vs. a listening endpoint)... - if (oldState != kState_Listening) - { - // Prevent further callbacks for incoming data. This has the effect of instructing - // LwIP to discard any further data received from the peer. - tcp_recv(mTCP, NULL); - - // If entering the Closed state... - if (State == kState_Closed) - { - // Prevent further callbacks to the error handler. - // - // Note: It is important to understand that LwIP can continue to make callbacks after - // a PCB has been closed via the tcp_close() API. In particular, LwIP will continue - // to call the 'data sent' callback to signal the acknowledgment of data that was - // sent, but not acknowledged, prior to the close call. Additionally, LwIP will call - // the error callback if the peer fails to respond in a timely manner to the either - // sent data or the FIN. Unfortunately, there is no callback in the case where the - // connection closes successfully. Because of this, it is impossible know definitively - // when LwIP will no longer make callbacks to its user. Thus we must block further - // callbacks to prevent them from happening after the endpoint has been freed. - // - tcp_err(mTCP, NULL); - - // If the endpoint is being closed without error, THEN call tcp_close() to close the underlying - // TCP connection gracefully, preserving any in-transit send data. - if (err == INET_NO_ERROR) - { - tcp_close(mTCP); - } - - // OTHERWISE, call tcp_abort() to abort the TCP connection, discarding any in-transit data. - else - { - tcp_abort(mTCP); - } - - // Discard the reference to the PCB to ensure there is no further interaction with it - // after this point. - mTCP = NULL; - mLwIPEndPointType = kLwIPEndPointType_Unknown; - } - } - - // OTHERWISE the endpoint was being used for listening, so simply close it. - else - { - tcp_close(mTCP); - - // Discard the reference to the PCB to ensure there is no further interaction with it - // after this point. - mTCP = NULL; - mLwIPEndPointType = kLwIPEndPointType_Unknown; - } - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - // If the socket hasn't been closed already... - if (mSocket != INET_INVALID_SOCKET_FD) - { - // If entering the Closed state - // OR if entering the Closing state, and there's no unsent data in the send queue - // THEN close the socket. - if (State == kState_Closed || - (State == kState_Closing && mSendQueue == NULL)) - { - chip::System::Layer& lSystemLayer = SystemLayer(); - - // If aborting the connection, ensure we send a TCP RST. - if (IsConnected(oldState) && err != INET_NO_ERROR) - { - lingerStruct.l_onoff = 1; - lingerStruct.l_linger = 0; - - if (setsockopt(mSocket, SOL_SOCKET, SO_LINGER, &lingerStruct, sizeof(lingerStruct)) != 0) - chipLogError(Inet, "SO_LINGER: %d", errno); - } - - if (close(mSocket) != 0 && err == INET_NO_ERROR) - err = chip::System::MapErrorPOSIX(errno); - mSocket = INET_INVALID_SOCKET_FD; - - // Wake the thread calling select so that it recognizes the socket is closed. - lSystemLayer.WakeSelect(); - } - } - - // Clear any results from select() that indicate pending I/O for the socket. - mPendingIO.Clear(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - // Stop the TCP UserTimeout timer if it is running. - StopTCPUserTimeoutTimer(); -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - - // If entering the Closed state... - if (State == kState_Closed) - { - // Clear clear the send and receive queues. - PacketBuffer::Free(mSendQueue); - mSendQueue = NULL; - PacketBuffer::Free(mRcvQueue); - mRcvQueue = NULL; - - // Call the appropriate app callback if allowed. - if (!suppressCallback) - { - if (oldState == kState_Connecting) - { - if (OnConnectComplete != NULL) - OnConnectComplete(this, err); - } - else if ((oldState == kState_Connected || oldState == kState_SendShutdown || - oldState == kState_ReceiveShutdown || oldState == kState_Closing) && - OnConnectionClosed != NULL) - OnConnectionClosed(this, err); - } - - // Decrement the ref count that was added when the connection started (in Connect()) or listening started (in Listen()). - // - // When using LwIP, post a callback to Release() rather than calling it directly. Since up-calls - // from LwIP are delivered as events (via the LwIP* methods), we must ensure that all events have been - // cleared from the queue before the end point gets freed, otherwise we'll end up accessing freed memory. - // We achieve this by first preventing further up-calls from LwIP (via the call to tcp_abort() above) - // and then queuing the Release() call to happen after all existing events have been processed. - // - if (oldState != kState_Ready && oldState != kState_Bound) - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP - DeferredFree(kReleaseDeferralErrorTactic_Ignore); -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP - Release(); -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP - } - } - - return err; -} - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT -void TCPEndPoint::TCPUserTimeoutHandler(chip::System::Layer* aSystemLayer, void* aAppState, chip::System::Error aError) -{ - TCPEndPoint * tcpEndPoint = reinterpret_cast(aAppState); - - VerifyOrDie((aSystemLayer != NULL) && (tcpEndPoint != NULL)); - - // Set the timer running flag to false - tcpEndPoint->mUserTimeoutTimerRunning = false; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - INET_ERROR err = INET_NO_ERROR; - bool isProgressing = false; - err = tcpEndPoint->CheckConnectionProgress(isProgressing); - SuccessOrExit(err); - - if (tcpEndPoint->mLastTCPKernelSendQueueLen == 0) - { -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - // If the kernel TCP send queue as well as the TCPEndPoint - // send queue have been flushed then notify application - // that all data has been acknowledged. - - if (tcpEndPoint->mSendQueue == NULL) - { - tcpEndPoint->SetTCPSendIdleAndNotifyChange(true); - } -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - } - else - // There is data in the TCP Send Queue - { - if (isProgressing) - { - // Data is flowing, so restart the UserTimeout timer - // to shift it forward while also resetting the max - // poll count. - - tcpEndPoint->StartTCPUserTimeoutTimer(); - } - else - { -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - // Data flow is not progressing. - // Decrement the remaining max TCP send queue polls. - - tcpEndPoint->mTCPSendQueueRemainingPollCount--; - - VerifyOrExit(tcpEndPoint->mTCPSendQueueRemainingPollCount != 0, - err = INET_ERROR_TCP_USER_TIMEOUT); - - // Restart timer to poll again - - tcpEndPoint->ScheduleNextTCPUserTimeoutPoll(tcpEndPoint->mTCPSendQueuePollPeriodMillis); -#else - // Close the connection as the TCP UserTimeout has expired - - ExitNow(err = INET_ERROR_TCP_USER_TIMEOUT); -#endif // !INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - } - } - -exit: - - if (err != INET_NO_ERROR) - { - // Close the connection as the TCP UserTimeout has expired - - tcpEndPoint->DoClose(err, false); - } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - // Close Connection as we have timed out and there is still - // data not sent out successfully. - - tcpEndPoint->DoClose(INET_ERROR_TCP_USER_TIMEOUT, false); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -} - -void TCPEndPoint::ScheduleNextTCPUserTimeoutPoll(uint32_t aTimeOut) -{ - chip::System::Layer& lSystemLayer = SystemLayer(); - - lSystemLayer.StartTimer(aTimeOut, TCPUserTimeoutHandler, this); -} - -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS -void TCPEndPoint::SetTCPSendIdleAndNotifyChange(bool aIsTCPSendIdle) -{ - if (mIsTCPSendIdle != aIsTCPSendIdle) - { - chipLogDetail(Inet, "TCP con send channel idle state changed : %s", aIsTCPSendIdle ? "false->true" : "true->false"); - - // Set the current Idle state - mIsTCPSendIdle = aIsTCPSendIdle; - - if (OnTCPSendIdleChanged) - { - OnTCPSendIdleChanged(this, mIsTCPSendIdle); - } - } -} -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - -void TCPEndPoint::StartTCPUserTimeoutTimer() -{ - uint32_t timeOut = mUserTimeoutMillis; - -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - //Set timeout to the poll interval - - timeOut = mTCPSendQueuePollPeriodMillis; - - // Reset the poll count - - mTCPSendQueueRemainingPollCount = MaxTCPSendQueuePolls(); -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - - ScheduleNextTCPUserTimeoutPoll(timeOut); - - mUserTimeoutTimerRunning = true; -} - -void TCPEndPoint::StopTCPUserTimeoutTimer() -{ - chip::System::Layer& lSystemLayer = SystemLayer(); - - lSystemLayer.CancelTimer(TCPUserTimeoutHandler, this); - - mUserTimeoutTimerRunning = false; -} - -void TCPEndPoint::RestartTCPUserTimeoutTimer() -{ - StopTCPUserTimeoutTimer(); - - StartTCPUserTimeoutTimer(); -} - -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -INET_ERROR TCPEndPoint::GetPCB(IPAddressType addrType) -{ - // IMMPORTANT: This method MUST be called with the LwIP stack LOCKED! - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - if (mTCP == NULL) - { - switch (addrType) - { - case kIPAddressType_IPv6: - mTCP = tcp_new_ip_type(IPADDR_TYPE_V6); - break; - -#if INET_CONFIG_ENABLE_IPV4 - case kIPAddressType_IPv4: - mTCP = tcp_new_ip_type(IPADDR_TYPE_V4); - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - default: - return INET_ERROR_WRONG_ADDRESS_TYPE; - } - - if (mTCP == NULL) - { - return INET_ERROR_NO_MEMORY; - } - else - { - mLwIPEndPointType = kLwIPEndPointType_TCP; - } - } - else - { - switch (IP_GET_TYPE(&mTCP->local_ip)) - { - case IPADDR_TYPE_V6: - if (addrType != kIPAddressType_IPv6) - return INET_ERROR_WRONG_ADDRESS_TYPE; - break; - -#if INET_CONFIG_ENABLE_IPV4 - case IPADDR_TYPE_V4: - if (addrType != kIPAddressType_IPv4) - return INET_ERROR_WRONG_ADDRESS_TYPE; - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - default: - break; - } - } -#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - if (mTCP == NULL) - { - if (addrType == kIPAddressType_IPv6) - mTCP = tcp_new_ip6(); -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - mTCP = tcp_new(); -#endif // INET_CONFIG_ENABLE_IPV4 - else - return INET_ERROR_WRONG_ADDRESS_TYPE; - if (mTCP == NULL) - { - return INET_ERROR_NO_MEMORY; - } - else - { - mLwIPEndPointType = kLwIPEndPointType_TCP; - } - } - else - { -#if INET_CONFIG_ENABLE_IPV4 - const IPAddressType pcbType = PCB_ISIPV6(mTCP) ? kIPAddressType_IPv6 : kIPAddressType_IPv4; -#else // !INET_CONFIG_ENABLE_IPV4 - const IPAddressType pcbType = kIPAddressType_IPv6; -#endif // !INET_CONFIG_ENABLE_IPV4 - if (addrType != pcbType) - return INET_ERROR_WRONG_ADDRESS_TYPE; - } -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - - return INET_NO_ERROR; -} - -void TCPEndPoint::HandleDataSent(uint16_t lenSent) -{ - if (IsConnected()) - { - // Consume data off the head of the send queue equal to the amount of data being acknowledged. - mSendQueue = mSendQueue->Consume(lenSent); - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - // Only change the UserTimeout timer if lenSent > 0, - // indicating progress being made in sending data - // across. - if (lenSent > 0) - { - if (mSendQueue == NULL) - { - // If the output queue has been flushed then stop the timer. - - StopTCPUserTimeoutTimer(); - -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - // Notify up if all outstanding data has been acknowledged - - SetTCPSendIdleAndNotifyChange(true); -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - } - else - { - // Progress is being made. So, shift the timer - // forward if it was started. - RestartTCPUserTimeoutTimer(); - } - } -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - - // Mark the connection as being active. - MarkActive(); - - // If requested, call the app's OnDataSent callback. - if (OnDataSent != NULL) - OnDataSent(this, lenSent); - - // If unsent data exists, attempt to sent it now... - if (mUnsentQueue != NULL) - DriveSending(); - - // If in the closing state and the send queue is now empty, attempt to transition to closed. - if (State == kState_Closing && mSendQueue == NULL) - DoClose(INET_NO_ERROR, false); - } -} - -void TCPEndPoint::HandleDataReceived(PacketBuffer *buf) -{ - // Only receive new data while in the Connected or SendShutdown states. - if (State == kState_Connected || State == kState_SendShutdown) - { - // Mark the connection as being active. - MarkActive(); - - // If we received a data buffer, queue it on the receive queue. If there's already data in - // the queue, compact the data into the head buffer. - if (buf != NULL) - { - if (mRcvQueue == NULL) - mRcvQueue = buf; - else - { - mRcvQueue->AddToEnd(buf); - mRcvQueue->CompactHead(); - } - } - - // Otherwise buf == NULL means the other side closed the connection, so ... - else { - - // If in the Connected state and the app has provided an OnPeerClose callback, - // enter the ReceiveShutdown state. Providing an OnPeerClose callback allows - // the app to decide whether to keep the send side of the connection open after - // the peer has closed. If no OnPeerClose is provided, we assume that the app - // wants to close both directions and automatically enter the Closing state. - if (State == kState_Connected && OnPeerClose != NULL) - State = kState_ReceiveShutdown; - else - State = kState_Closing; - - // Call the app's OnPeerClose. - if (OnPeerClose != NULL) - OnPeerClose(this); - } - - // Drive the received data into the app. - DriveReceiving(); - } - else - PacketBuffer::Free(buf); -} - -void TCPEndPoint::HandleIncomingConnection(TCPEndPoint *conEP) -{ - INET_ERROR err = INET_NO_ERROR; - IPAddress peerAddr; - uint16_t peerPort; - - if (State == kState_Listening) - { - // If there's no callback available, fail with an error. - if (OnConnectionReceived == NULL) - err = INET_ERROR_NO_CONNECTION_HANDLER; - - // Extract the peer's address information. - if (err == INET_NO_ERROR) - err = conEP->GetPeerInfo(&peerAddr, &peerPort); - - // If successful, call the app's callback function. - if (err == INET_NO_ERROR) - OnConnectionReceived(this, conEP, peerAddr, peerPort); - - // Otherwise clean up and call the app's error callback. - else if (OnAcceptError != NULL) - OnAcceptError(this, err); - } - else - err = INET_ERROR_INCORRECT_STATE; - - // If something failed above, abort and free the connection end point. - if (err != INET_NO_ERROR) - conEP->Free(); -} - -void TCPEndPoint::HandleError(INET_ERROR err) -{ - if (State == kState_Listening) - { - if (OnAcceptError != NULL) - OnAcceptError(this, err); - } - else - DoClose(err, false); -} - -err_t TCPEndPoint::LwIPHandleConnectComplete(void *arg, struct tcp_pcb *tpcb, err_t lwipErr) -{ - err_t res = ERR_OK; - - if (arg != NULL) - { - INET_ERROR conErr; - TCPEndPoint* ep = static_cast(arg); - chip::System::Layer& lSystemLayer = ep->SystemLayer(); - - if (lwipErr == ERR_OK) - { - // Setup LwIP callback functions for data transmission. - tcp_recv(ep->mTCP, LwIPHandleDataReceived); - tcp_sent(ep->mTCP, LwIPHandleDataSent); - } - - // Post callback to HandleConnectComplete. - conErr = chip::System::MapErrorLwIP(lwipErr); - if (lSystemLayer.PostEvent(*ep, kInetEvent_TCPConnectComplete, (uintptr_t)conErr) != INET_NO_ERROR) - res = ERR_ABRT; - } - else - res = ERR_ABRT; - - if (res != ERR_OK) - tcp_abort(tpcb); - - return res; -} - -err_t TCPEndPoint::LwIPHandleIncomingConnection(void *arg, struct tcp_pcb *tpcb, err_t lwipErr) -{ - INET_ERROR err = chip::System::MapErrorLwIP(lwipErr); - - if (arg != NULL) - { - TCPEndPoint* listenEP = static_cast(arg); - TCPEndPoint* conEP = NULL; - chip::System::Layer& lSystemLayer = listenEP->SystemLayer(); - - // Tell LwIP we've accepted the connection so it can decrement the listen PCB's pending_accepts counter. - tcp_accepted(listenEP->mTCP); - - // If we did in fact receive a connection, rather than an error, attempt to allocate an end point object. - // - // NOTE: Although most of the LwIP callbacks defer the real work to happen on the endpoint's thread - // (by posting events to the thread's event queue) we can't do that here because as soon as this - // function returns, LwIP is free to begin calling callbacks on the new PCB. For that to work we need - // to have an end point associated with the PCB. - // - if (err == INET_NO_ERROR) - { - InetLayer& lInetLayer = listenEP->Layer(); - - err = lInetLayer.NewTCPEndPoint(&conEP); - } - - // Ensure that TCP timers have been started - if (err == INET_NO_ERROR) - { - err = start_tcp_timers(); - } - - // If successful in allocating an end point... - if (err == INET_NO_ERROR) - { - // Put the new end point into the Connected state. - conEP->State = kState_Connected; - conEP->mTCP = tpcb; - conEP->mLwIPEndPointType = kLwIPEndPointType_TCP; - conEP->Retain(); - - // Setup LwIP callback functions for the new PCB. - tcp_arg(tpcb, conEP); - tcp_recv(tpcb, LwIPHandleDataReceived); - tcp_sent(tpcb, LwIPHandleDataSent); - tcp_err(tpcb, LwIPHandleError); - - // Post a callback to the HandleConnectionReceived() function, passing it the new end point. - if (lSystemLayer.PostEvent(*listenEP, kInetEvent_TCPConnectionReceived, (uintptr_t)conEP) != INET_NO_ERROR) - { - err = INET_ERROR_CONNECTION_ABORTED; - conEP->Release(); // for the Retain() above - conEP->Release();// for the Retain() in NewTCPEndPoint() - } - } - - // Otherwise, there was an error accepting the connection, so post a callback to the HandleError function. - else - lSystemLayer.PostEvent(*listenEP, kInetEvent_TCPError, (uintptr_t)err); - } - else - err = INET_ERROR_CONNECTION_ABORTED; - - if (err != INET_NO_ERROR && tpcb != NULL) - { - tcp_abort(tpcb); - return ERR_ABRT; - } - else - { - return ERR_OK; - } -} - -err_t TCPEndPoint::LwIPHandleDataReceived(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) -{ - err_t res = ERR_OK; - - if (arg != NULL) - { - TCPEndPoint* ep = static_cast(arg); - chip::System::Layer& lSystemLayer = ep->SystemLayer(); - - // Post callback to HandleDataReceived. - if (lSystemLayer.PostEvent(*ep, kInetEvent_TCPDataReceived, (uintptr_t)p) != INET_NO_ERROR) - res = ERR_ABRT; - } - else - res = ERR_ABRT; - - if (res != ERR_OK) - tcp_abort(tpcb); - - return res; -} - -err_t TCPEndPoint::LwIPHandleDataSent(void *arg, struct tcp_pcb *tpcb, u16_t len) -{ - err_t res = ERR_OK; - - if (arg != NULL) - { - TCPEndPoint* ep = static_cast(arg); - chip::System::Layer& lSystemLayer = ep->SystemLayer(); - - // Post callback to HandleDataReceived. - if (lSystemLayer.PostEvent(*ep, kInetEvent_TCPDataSent, (uintptr_t)len) != INET_NO_ERROR) - res = ERR_ABRT; - } - else - res = ERR_ABRT; - - if (res != ERR_OK) - tcp_abort(tpcb); - - return res; -} - -void TCPEndPoint::LwIPHandleError(void *arg, err_t lwipErr) -{ - if (arg != NULL) - { - TCPEndPoint* ep = static_cast(arg); - chip::System::Layer& lSystemLayer = ep->SystemLayer(); - - // At this point LwIP has already freed the PCB. Since the thread that owns the TCPEndPoint may - // try to use the PCB before it receives the TCPError event posted below, we set the PCB to NULL - // as a means to signal the other thread that the connection has been aborted. The implication - // of this is that the mTCP field is shared state between the two threads and thus must only be - // accessed with the LwIP lock held. - ep->mTCP = NULL; - ep->mLwIPEndPointType = kLwIPEndPointType_Unknown; - - // Post callback to HandleError. - INET_ERROR err = chip::System::MapErrorLwIP(lwipErr); - lSystemLayer.PostEvent(*ep, kInetEvent_TCPError, (uintptr_t)err); - } -} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -INET_ERROR TCPEndPoint::BindSrcAddrFromIntf(IPAddressType addrType, InterfaceId intf) -{ - INET_ERROR err = INET_NO_ERROR; - - // If we are trying to make a TCP connection over a 'specified target interface', - // then we bind the TCPEndPoint to an IP address on that target interface - // and use that address as the source address for that connection. This is - // done in the event that directly binding the connection to the target - // interface is not allowed due to insufficient privileges. - IPAddress curAddr = IPAddress::Any; - InterfaceId curIntfId = INET_NULL_INTERFACEID; - bool ipAddrFound = false; - - VerifyOrExit(State != kState_Bound, err = INET_ERROR_NOT_SUPPORTED); - - for (InterfaceAddressIterator addrIter; addrIter.HasCurrent(); addrIter.Next()) - { - curAddr = addrIter.GetAddress(); - curIntfId = addrIter.GetInterface(); - - if (curIntfId == intf) - { - // Search for an IPv4 address on the TargetInterface - -#if INET_CONFIG_ENABLE_IPV4 - if (addrType == kIPAddressType_IPv4) - { - if (curAddr.IsIPv4()) - { - // Bind to the IPv4 address of the TargetInterface - ipAddrFound = true; - err = Bind(kIPAddressType_IPv4, curAddr, 0, true); - SuccessOrExit(err); - - break; - } - } -#endif // INET_CONFIG_ENABLE_IPV4 - if (addrType == kIPAddressType_IPv6) - { - // Select an IPv6 address on the interface that is not - // a link local or a multicast address. - //TODO: Define a proper IPv6GlobalUnicast address checker. - if (!curAddr.IsIPv4() && !curAddr.IsIPv6LinkLocal() && - !curAddr.IsMulticast()) - { - // Bind to the IPv6 address of the TargetInterface - ipAddrFound = true; - err = Bind(kIPAddressType_IPv6, curAddr, 0, true); - SuccessOrExit(err); - - break; - } - } - } - } - - VerifyOrExit(ipAddrFound, err = INET_ERROR_NOT_SUPPORTED); - -exit: - return err; -} - -INET_ERROR TCPEndPoint::GetSocket(IPAddressType addrType) -{ - if (mSocket == INET_INVALID_SOCKET_FD) - { - int family; - if (addrType == kIPAddressType_IPv6) - family = PF_INET6; -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - family = PF_INET; -#endif // INET_CONFIG_ENABLE_IPV4 - else - return INET_ERROR_WRONG_ADDRESS_TYPE; - mSocket = ::socket(family, SOCK_STREAM | SOCK_FLAGS, 0); - if (mSocket == -1) - return chip::System::MapErrorPOSIX(errno); - mAddrType = addrType; - - // If creating an IPv6 socket, tell the kernel that it will be IPv6 only. This makes it - // posible to bind two sockets to the same port, one for IPv4 and one for IPv6. -#ifdef IPV6_V6ONLY - if (family == PF_INET6) - { - int one = 1; - setsockopt(mSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &one, sizeof(one)); - } -#endif // defined(IPV6_V6ONLY) - - // On systems that support it, disable the delivery of SIGPIPE signals when writing to a closed - // socket. -#ifdef SO_NOSIGPIPE - { - int one = 1; - int res = setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); - if (res != 0) - { - chipLogError(Inet, "SO_NOSIGPIPE: %d", errno); - } - } -#endif // defined(SO_NOSIGPIPE) - } - else if (mAddrType != addrType) - return INET_ERROR_INCORRECT_STATE; - - return INET_NO_ERROR; -} - -SocketEvents TCPEndPoint::PrepareIO() -{ - SocketEvents ioType; - - // If initiating a new connection... - // OR if connected and there is data to be sent... - // THEN arrange for the kernel to alert us when the socket is ready to be written. - if (State == kState_Connecting || (IsConnected() && mSendQueue != NULL)) - ioType.SetWrite(); - - // If listening for incoming connections and the app is ready to receive a connection... - // OR if in a state where receiving is allowed, and the app is ready to receive data... - // THEN arrange for the kernel to alert us when the socket is ready to be read. - if ((State == kState_Listening && OnConnectionReceived != NULL) || - ((State == kState_Connected || State == kState_SendShutdown) && ReceiveEnabled && OnDataReceived != NULL)) - ioType.SetRead(); - - return ioType; -} - -void TCPEndPoint::HandlePendingIO() -{ - // Prevent the end point from being freed while in the middle of a callback. - Retain(); - - // If in the Listening state, and the app is ready to receive a connection, and there is a connection - // ready to be received on the socket, process the incoming connection. - if (State == kState_Listening) - { - if (OnConnectionReceived != NULL && mPendingIO.IsReadable()) - HandleIncomingConnection(); - } - - // If in the processes of initiating a connection... - else if (State == kState_Connecting) - { - // The socket being writable indicates the connection has completed (successfully or otherwise). - if (mPendingIO.IsWriteable()) - { - // Get the connection result from the socket. - int osConRes; - socklen_t optLen = sizeof(osConRes); - if (getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &osConRes, &optLen) != 0) - osConRes = errno; - INET_ERROR conRes = chip::System::MapErrorPOSIX(osConRes); - - // Process the connection result. - HandleConnectComplete(conRes); - } - } - - else - { - // If in a state where sending is allowed, and there is data to be sent, and the socket is ready for - // writing, drive outbound data into the connection. - if (IsConnected() && mSendQueue != NULL && mPendingIO.IsWriteable()) - DriveSending(); - - // If in a state were receiving is allowed, and the app is ready to receive data, and data is ready - // on the socket, receive inbound data from the connection. - if ((State == kState_Connected || State == kState_SendShutdown) && ReceiveEnabled && OnDataReceived != NULL && mPendingIO.IsReadable()) - ReceiveData(); - } - - mPendingIO.Clear(); - - Release(); -} - -void TCPEndPoint::ReceiveData() -{ - PacketBuffer *rcvBuf; - bool isNewBuf = true; - - if (mRcvQueue == NULL) - rcvBuf = PacketBuffer::New(0); - else - { - rcvBuf = mRcvQueue; - for (PacketBuffer *nextBuf = rcvBuf->Next(); nextBuf != NULL; rcvBuf = nextBuf, nextBuf = nextBuf->Next()) - ; - - if (rcvBuf->AvailableDataLength() == 0) - rcvBuf = PacketBuffer::New(0); - else - { - isNewBuf = false; - rcvBuf->CompactHead(); - } - } - - if (rcvBuf == NULL) - { - DoClose(INET_ERROR_NO_MEMORY, false); - return; - } - - // Attempt to receive data from the socket. - ssize_t rcvLen = recv(mSocket, rcvBuf->Start() + rcvBuf->DataLength(), rcvBuf->AvailableDataLength(), 0); - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - INET_ERROR err; - bool isProgressing = false; - - err = CheckConnectionProgress(isProgressing); - if (err != INET_NO_ERROR) - { - DoClose(err, false); - - return; - } - - if (mLastTCPKernelSendQueueLen == 0) - { - // If the output queue has been flushed then stop the timer. - - StopTCPUserTimeoutTimer(); - -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - // Notify up if all outstanding data has been acknowledged - - if (mSendQueue == NULL) - { - SetTCPSendIdleAndNotifyChange(true); - } -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - } - else if (isProgressing && mUserTimeoutTimerRunning) - { - // Progress is being made. So, shift the timer - // forward if it was started. - RestartTCPUserTimeoutTimer(); - } -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - // If an error occurred, abort the connection. - if (rcvLen < 0) - { - int systemErrno = errno; - - if (isNewBuf) - { - PacketBuffer::Free(rcvBuf); - } - - if (systemErrno == EAGAIN) - { - // Note: in this case, we opt to not retry the recv call, - // and instead we expect that the read flags will get - // reset correctly upon a subsequent return from the - // select call. - chipLogError(Inet, "recv: EAGAIN, will retry"); - - return; - } - - DoClose(chip::System::MapErrorPOSIX(systemErrno), false); - } - - else - { - // Mark the connection as being active. - MarkActive(); - - // If the peer closed their end of the connection... - if (rcvLen == 0) - { - if (isNewBuf) - PacketBuffer::Free(rcvBuf); - - // If in the Connected state and the app has provided an OnPeerClose callback, - // enter the ReceiveShutdown state. Providing an OnPeerClose callback allows - // the app to decide whether to keep the send side of the connection open after - // the peer has closed. If no OnPeerClose is provided, we assume that the app - // wants to close both directions and automatically enter the Closing state. - if (State == kState_Connected && OnPeerClose != NULL) - State = kState_ReceiveShutdown; - else - State = kState_Closing; - - // Call the app's OnPeerClose. - if (OnPeerClose != NULL) - OnPeerClose(this); - } - - // Otherwise, add the new data onto the receive queue. - else if (isNewBuf) - { - rcvBuf->SetDataLength(rcvBuf->DataLength() + (uint16_t) rcvLen); - if (mRcvQueue == NULL) - mRcvQueue = rcvBuf; - else - mRcvQueue->AddToEnd(rcvBuf); - } - - else - rcvBuf->SetDataLength(rcvBuf->DataLength() + (uint16_t) rcvLen, mRcvQueue); - } - - // Drive any received data into the app. - DriveReceiving(); -} - -void TCPEndPoint::HandleIncomingConnection() -{ - INET_ERROR err = INET_NO_ERROR; - TCPEndPoint *conEP = NULL; - IPAddress peerAddr; - uint16_t peerPort; - - union - { - sockaddr any; - sockaddr_in in; - sockaddr_in6 in6; - } sa; - memset(&sa, 0, sizeof(sa)); - socklen_t saLen = sizeof(sa); - - // Accept the new connection. - int conSocket = accept(mSocket, &sa.any, &saLen); - if (conSocket == -1) - err = chip::System::MapErrorPOSIX(errno); - - // If there's no callback available, fail with an error. - if (err == INET_NO_ERROR && OnConnectionReceived == NULL) - err = INET_ERROR_NO_CONNECTION_HANDLER; - - // Extract the peer's address information. - if (err == INET_NO_ERROR) - { - if (sa.any.sa_family == AF_INET6) - { - peerAddr = IPAddress::FromIPv6(sa.in6.sin6_addr); - peerPort = ntohs(sa.in6.sin6_port); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (sa.any.sa_family == AF_INET) - { - peerAddr = IPAddress::FromIPv4(sa.in.sin_addr); - peerPort = ntohs(sa.in.sin_port); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - err = INET_ERROR_INCORRECT_STATE; - } - - // Attempt to allocate an end point object. - if (err == INET_NO_ERROR) - { - InetLayer& lInetLayer = Layer(); - - err = lInetLayer.NewTCPEndPoint(&conEP); - } - - // If all went well... - if (err == INET_NO_ERROR) - { - // Put the new end point into the Connected state. - conEP->State = kState_Connected; - conEP->mSocket = conSocket; -#if INET_CONFIG_ENABLE_IPV4 - conEP->mAddrType = (sa.any.sa_family == AF_INET6) ? kIPAddressType_IPv6 : kIPAddressType_IPv4; -#else // !INET_CONFIG_ENABLE_IPV4 - conEP->mAddrType = kIPAddressType_IPv6; -#endif // !INET_CONFIG_ENABLE_IPV4 - conEP->Retain(); - - // Call the app's callback function. - OnConnectionReceived(this, conEP, peerAddr, peerPort); - } - - // Otherwise immediately close the connection, clean up and call the app's error callback. - else - { - if (conSocket != -1) - close(conSocket); - if (conEP != NULL) - { - if (conEP->State == kState_Connected) - conEP->Release(); - conEP->Release(); - } - if (OnAcceptError != NULL) - OnAcceptError(this, err); - } -} - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT -/** - * This function probes the TCP output queue and checks if data is successfully - * being transferred to the other end. - */ -INET_ERROR TCPEndPoint::CheckConnectionProgress(bool &isProgressing) -{ - INET_ERROR err = INET_NO_ERROR; - int currPendingBytes = 0; - - // Fetch the bytes pending successful transmission in the TCP out queue. - - if (ioctl(mSocket, TIOCOUTQ, &currPendingBytes) < 0) - { - ExitNow(err = chip::System::MapErrorPOSIX(errno)); - } - - if ((currPendingBytes != 0) && - (mBytesWrittenSinceLastProbe + mLastTCPKernelSendQueueLen == static_cast(currPendingBytes))) - { - // No progress has been made - - isProgressing = false; - } - else - { - // Data is flowing successfully - - isProgressing = true; - } - - // Reset the value of the bytes written since the last probe into the tcp - // outqueue was made and update the last tcp outqueue sample. - - mBytesWrittenSinceLastProbe = 0; - - mLastTCPKernelSendQueueLen = currPendingBytes; - -exit: - return err; -} -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -} // namespace Inet -} // namespace chip diff --git a/src/inet/TCPEndPoint.h b/src/inet/TCPEndPoint.h deleted file mode 100644 index 3361375efaa65a..00000000000000 --- a/src/inet/TCPEndPoint.h +++ /dev/null @@ -1,682 +0,0 @@ -/* - * - * - * - * 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 header file defines the Inet::TCPEndPoint - * class, where the Nest Inet Layer encapsulates methods for - * interacting with TCP transport endpoints (SOCK_DGRAM sockets - * on Linux and BSD-derived systems) or LwIP TCP protocol - * control blocks, as the system is configured accordingly. - */ - -#ifndef TCPENDPOINT_H -#define TCPENDPOINT_H - -#include -#include - -#include - -namespace chip { -namespace Inet { - -class InetLayer; - -/** - * @brief Objects of this class represent TCP transport endpoints. - * - * @details - * Nest Inet Layer encapsulates methods for interacting with TCP transport - * endpoints (SOCK_STREAM sockets on Linux and BSD-derived systems) or LwIP - * TCP protocol control blocks, as the system is configured accordingly. - */ -class DLL_EXPORT TCPEndPoint : public EndPointBasis -{ - friend class InetLayer; - -public: - /** Control switch indicating whether the application is receiving data. */ - bool ReceiveEnabled; - - /** - * @brief Basic dynamic state of the underlying endpoint. - * - * @details - * Objects are initialized in the "ready" state, proceed to subsequent - * states corresponding to a simplification of the states of the TCP - * transport state machine. - * - * @note - * The \c kBasisState_Closed state enumeration is mapped to \c kState_Ready for historical binary-compatibility reasons. The - * existing \c kState_Closed exists to identify separately the distinction between "not opened yet" and "previously opened now - * closed" that existed previously in the \c kState_Ready and \c kState_Closed states. - */ - enum { - kState_Ready = kBasisState_Closed, /**< Endpoint initialized, but not bound. */ - kState_Bound = 1, /**< Endpoint bound, but not listening. */ - kState_Listening = 2, /**< Endpoint receiving connections. */ - kState_Connecting = 3, /**< Endpoint attempting to connect. */ - kState_Connected = 4, /**< Endpoint connected, ready for tx/rx. */ - kState_SendShutdown = 5, /**< Endpoint initiated its half-close. */ - kState_ReceiveShutdown = 6, /**< Endpoint responded to half-close. */ - kState_Closing = 7, /**< Endpoint closing bidirectionally. */ - kState_Closed = 8 /**< Endpoint closed, ready for release. */ - } State; - - /** - * @brief Bind the endpoint to an interface IP address. - * - * @param[in] addrType the protocol version of the IP address - * @param[in] addr the IP address (must be an interface address) - * @param[in] port the TCP port - * @param[in] reuseAddr option to share binding with other endpoints - * - * @retval INET_NO_ERROR success: endpoint bound to address - * @retval INET_ERROR_INCORRECT_STATE endpoint has been bound previously - * @retval INET_NO_MEMORY insufficient memory for endpoint - * - * @retval INET_ERROR_WRONG_PROTOCOL_TYPE - * \c addrType does not match \c IPVer. - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * \c addrType is \c kIPAddressType_Any, or the type of \c addr is not - * equal to \c addrType. - * - * @retval other another system or platform error - * - * @details - * Binds the endpoint to the specified network interface IP address. - * - * On LwIP, this method must not be called with the LwIP stack lock - * already acquired. - */ - INET_ERROR Bind(IPAddressType addrType, IPAddress addr, uint16_t port, bool reuseAddr = false); - - /** - * @brief Prepare the endpoint to receive TCP messages. - * - * @param[in] backlog maximum depth of connection acceptance queue - * - * @retval INET_NO_ERROR success: endpoint ready to receive messages. - * @retval INET_ERROR_INCORRECT_STATE endpoint is already listening. - * - * @details - * If \c State is already \c kState_Listening, then no operation is - * performed, otherwise the \c State is set to \c kState_Listening and - * the endpoint is prepared to received TCP messages, according to the - * semantics of the platform. - * - * On some platforms, the \c backlog argument is not used (the depth of - * the queue is fixed; only one connection may be accepted at a time). - * - * On LwIP systems, this method must not be called with the LwIP stack - * lock already acquired - */ - INET_ERROR Listen(uint16_t backlog); - - /** - * @brief Initiate a TCP connection. - * - * @param[in] addr the destination IP address - * @param[in] port the destination TCP port - * @param[in] intf an optional network interface indicator - * - * @retval INET_NO_ERROR success: \c msg is queued for transmit. - * @retval INET_ERROR_NOT_IMPLEMENTED system implementation not complete. - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * the destination address and the bound interface address do not - * have matching protocol versions or address type, or the destination - * address is an IPv6 link-local address and \c intf is not specified. - * - * @retval other another system or platform error - * - * @details - * If possible, then this method initiates a TCP connection to the - * destination \c addr (with \c intf used as the scope - * identifier for IPv6 link-local destinations) and \c port. - */ - INET_ERROR Connect(IPAddress addr, uint16_t port, InterfaceId intf = INET_NULL_INTERFACEID); - - /** - * @brief Extract IP address and TCP port of remote endpoint. - * - * @param[out] retAddr IP address of remote endpoint. - * @param[out] retPort TCP port of remote endpoint. - * - * @retval INET_NO_ERROR success: address and port extracted. - * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * @retval INET_ERROR_CONNECTION_ABORTED TCP connection no longer open. - * - * @details - * Do not use \c NULL pointer values for either argument. - */ - INET_ERROR GetPeerInfo(IPAddress *retAddr, uint16_t *retPort) const; - - /** - * @brief Extract IP address and TCP port of local endpoint. - * - * @param[out] retAddr IP address of local endpoint. - * @param[out] retPort TCP port of local endpoint. - * - * @retval INET_NO_ERROR success: address and port extracted. - * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * @retval INET_ERROR_CONNECTION_ABORTED TCP connection no longer open. - * - * @details - * Do not use \c NULL pointer values for either argument. - */ - INET_ERROR GetLocalInfo(IPAddress *retAddr, uint16_t *retPort); - - /** - * @brief Send message text on TCP connection. - * - * @param[out] data Message text to send. - * @param[out] push If \c true, then send immediately, otherwise queue. - * - * @retval INET_NO_ERROR success: address and port extracted. - * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * - * @details - * The chip::System::PacketBuffer::Free method is called on the \c data argument - * regardless of whether the transmission is successful or failed. - */ - INET_ERROR Send(chip::System::PacketBuffer *data, bool push = true); - - /** - * @brief Disable reception. - * - * @details - * Disable all event handlers. Data sent to an endpoint that disables - * reception will be acknowledged until the receive window is exhausted. - */ - void DisableReceive(void); - - /** - * @brief Enable reception. - * - * @details - * Enable all event handlers. Data sent to an endpoint that disables - * reception will be acknowledged until the receive window is exhausted. - */ - void EnableReceive(void); - - /** - * @brief EnableNoDelay - */ - INET_ERROR EnableNoDelay(void); - - /** - * @brief Enable the TCP "keep-alive" option. - * - * @param[in] interval time in seconds between probe requests. - * @param[in] timeoutCount number of probes to send before timeout. - * - * @retval INET_NO_ERROR success: address and port extracted. - * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * @retval INET_ERROR_CONNECTION_ABORTED TCP connection no longer open. - * @retval INET_ERROR_NOT_IMPLEMENTED system implementation not complete. - * - * @retval other another system or platform error - * - * @details - * Start automatically transmitting TCP "keep-alive" probe segments every - * \c interval seconds. The connection will abort automatically after - * receiving a negative response, or after sending \c timeoutCount - * probe segments without receiving a positive response. - * - * See RFC 1122, section 4.2.3.6 for specification details. - */ - INET_ERROR EnableKeepAlive(uint16_t interval, uint16_t timeoutCount); - - /** - * @brief Disable the TCP "keep-alive" option. - * - * @retval INET_NO_ERROR success: address and port extracted. - * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * @retval INET_ERROR_CONNECTION_ABORTED TCP connection no longer open. - * @retval INET_ERROR_NOT_IMPLEMENTED system implementation not complete. - * - * @retval other another system or platform error - */ - INET_ERROR DisableKeepAlive(void); - - /** - * @brief Set the TCP TCP_USER_TIMEOUT socket option. - * - * @param[in] userTimeoutMillis Tcp user timeout value in milliseconds. - * - * @retval INET_NO_ERROR success: address and port extracted. - * @retval INET_ERROR_NOT_IMPLEMENTED system implementation not complete. - * - * @retval other another system or platform error - * - * @details - * When the value is greater than 0, it specifies the maximum amount of - * time in milliseconds that transmitted data may remain - * unacknowledged before TCP will forcibly close the - * corresponding connection. If the option value is specified as 0, - * TCP will to use the system default. - * See RFC 5482, for further details. - */ - INET_ERROR SetUserTimeout(uint32_t userTimeoutMillis); - - /** - * @brief Acknowledge receipt of message text. - * - * @param[in] len number of bytes to acknowledge. - * - * @retval INET_NO_ERROR success: reception acknowledged. - * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * @retval INET_ERROR_CONNECTION_ABORTED TCP connection no longer open. - * - * @details - * Use this method to acknowledge reception of all or part of the data - * received. The operational semantics are undefined if \c len is larger - * than the total outstanding unacknowledged received data. - */ - INET_ERROR AckReceive(uint16_t len); - - /** - * @brief Push message text back to the head of the receive queue. - * - * @param[out] data Message text to push. - * - * @retval INET_NO_ERROR success: reception acknowledged. - * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * - * @details - * This method may only be called by data reception event handlers to - * put an unacknowledged portion of data back on the receive queue. The - * operational semantics are undefined if the caller is outside the scope - * of a data reception event handler, \c data is not the \c chip::System::PacketBuffer - * provided to the handler, or \c data does not contain the unacknowledged - * portion remaining after the bytes acknowledged by a prior call to the - * AckReceive(uint16_t len) method. - */ - INET_ERROR PutBackReceivedData(chip::System::PacketBuffer *data); - - /** - * @brief Extract the length of the data awaiting first transmit. - * - * @return Number of untransmitted bytes in the transmit queue. - */ - uint32_t PendingSendLength(void); - - /** - * @brief Extract the length of the unacknowledged receive data. - * - * @return Number of bytes in the receive queue that have not yet been - * acknowledged with AckReceive(uint16_t len). - */ - uint32_t PendingReceiveLength(void); - - /** - * @brief Initiate TCP half close, in other words, finished with sending. - * - * @retval INET_NO_ERROR success: address and port extracted. - * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * - * @retval other another system or platform error - */ - INET_ERROR Shutdown(void); - - /** - * @brief Initiate TCP full close, in other words, finished with both send and - * receive. - * - * @retval INET_NO_ERROR success: address and port extracted. - * @retval INET_ERROR_INCORRECT_STATE TCP connection not established. - * - * @retval other another system or platform error - */ - INET_ERROR Close(void); - - /** - * @brief Abortively close the endpoint, in other words, send RST packets. - */ - void Abort(void); - - /** - * @brief Initiate (or continue) TCP full close, ignoring errors. - * - * @details - * The object is returned to the free pool, and all remaining user - * references are subsequently invalid. - */ - void Free(void); - - /** - * @brief Extract whether TCP connection is established. - */ - bool IsConnected(void) const; - - void SetConnectTimeout(const uint32_t connTimeoutMsecs); - -#if INET_TCP_IDLE_CHECK_INTERVAL > 0 - /** - * @brief Set timer event for idle activity. - * - * @param[in] timeoutMS - * - * @details - * Set the idle timer interval to \c timeoutMS milliseconds. A zero - * time interval implies the idle timer is disabled. - */ - void SetIdleTimeout(uint32_t timeoutMS); -#endif // INET_TCP_IDLE_CHECK_INTERVAL > 0 - - /** - * @brief Note activity, in other words, reset the idle timer. - * - * @details - * Reset the idle timer to zero. - */ - void MarkActive(void); - - /** - * @brief Obtain an identifier for the endpoint. - * - * @return Returns an opaque unique identifier for use logs. - */ - uint16_t LogId(void); - - /** - * @brief Type of connection establishment event handling function. - * - * @param[in] endPoint The TCP endpoint associated with the event. - * @param[in] err \c INET_NO_ERROR if success, else another code. - * - * @details - * Provide a function of this type to the \c OnConnectComplete delegate - * member to process connection establishment events on \c endPoint. The - * \c err argument distinguishes successful connections from failures. - */ - typedef void (*OnConnectCompleteFunct)(TCPEndPoint *endPoint, INET_ERROR err); - - /** - * The endpoint's connection establishment event handling function - * delegate. - */ - OnConnectCompleteFunct OnConnectComplete; - - /** - * @brief Type of data reception event handling function. - * - * @param[in] endPoint The TCP endpoint associated with the event. - * @param[in] data The data received. - * - * @details - * Provide a function of this type to the \c OnDataReceived delegate - * member to process data reception events on \c endPoint where \c data - * is the message text received. - * - * A data reception event handler must acknowledge data processed using - * the \c AckReceive method. The \c Free method on the data buffer must - * also be invoked unless the \c PutBackReceivedData is used instead. - */ - typedef void (*OnDataReceivedFunct)(TCPEndPoint *endPoint, chip::System::PacketBuffer *data); - - /** - * The endpoint's message text reception event handling function delegate. - */ - OnDataReceivedFunct OnDataReceived; - - /** - * @brief Type of data transmission event handling function. - * - * @param[in] endPoint The TCP endpoint associated with the event. - * @param[in] len Number of bytes added to the transmit window. - * - * @details - * Provide a function of this type to the \c OnDataSent delegate - * member to process data transmission events on \c endPoint where \c len - * is the length of the message text added to the TCP transmit window, - * which are eligible for sending by the underlying network stack. - */ - typedef void (*OnDataSentFunct)(TCPEndPoint *endPoint, uint16_t len); - - /** - * The endpoint's message text transmission event handling function - * delegate. - */ - OnDataSentFunct OnDataSent; - - /** - * @brief Type of connection establishment event handling function. - * - * @param[in] endPoint The TCP endpoint associated with the event. - * @param[in] err \c INET_NO_ERROR if success, else another code. - * - * @details - * Provide a function of this type to the \c OnConnectionClosed delegate - * member to process connection termination events on \c endPoint. The - * \c err argument distinguishes successful terminations from failures. - */ - typedef void (*OnConnectionClosedFunct)(TCPEndPoint *endPoint, INET_ERROR err); - - /** The endpoint's close event handling function delegate. */ - OnConnectionClosedFunct OnConnectionClosed; - - /** - * @brief Type of half-close reception event handling function. - * - * @param[in] endPoint The TCP endpoint associated with the event. - * - * @details - * Provide a function of this type to the \c OnPeerClose delegate member - * to process connection termination events on \c endPoint. - */ - typedef void (*OnPeerCloseFunct)(TCPEndPoint *endPoint); - - /** The endpoint's half-close receive event handling function delegate. */ - OnPeerCloseFunct OnPeerClose; - - /** - * @brief Type of connection received event handling function. - * - * @param[in] listeningEndPoint The listening TCP endpoint. - * @param[in] conEndPoint The newly received TCP endpoint. - * @param[in] peerAddr The IP address of the remote peer. - * @param[in] peerPort The TCP port of the remote peer. - * - * @details - * Provide a function of this type to the \c OnConnectionReceived delegate - * member to process connection reception events on \c listeningEndPoint. - * The newly received endpoint \c conEndPoint is located at IP address - * \c peerAddr and TCP port \c peerPort. - */ - typedef void (*OnConnectionReceivedFunct)(TCPEndPoint *listeningEndPoint, TCPEndPoint *conEndPoint, - const IPAddress &peerAddr, uint16_t peerPort); - - /** The endpoint's connection receive event handling function delegate. */ - OnConnectionReceivedFunct OnConnectionReceived; - - /** - * @brief Type of connection acceptance error event handling function. - * - * @param[in] endPoint The TCP endpoint associated with the event. - * @param[in] err The reason for the error. - * - * @details - * Provide a function of this type to the \c OnAcceptError delegate - * member to process connection acceptance error events on \c endPoint. The - * \c err argument provides specific detail about the type of the error. - */ - typedef void (*OnAcceptErrorFunct)(TCPEndPoint *endPoint, INET_ERROR err); - - /** - * The endpoint's connection acceptance event handling function delegate. - */ - OnAcceptErrorFunct OnAcceptError; - -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - /** - * @brief Type of TCP SendIdle changed signal handling function. - * - * @param[in] endPoint The TCP endpoint associated with the event. - * - * @param[in] isIdle True if the send channel of the TCP endpoint - * is Idle, otherwise false. - * @details - * Provide a function of this type to the \c OnTCPSendIdleChanged delegate - * member to process the event of the send channel of the TCPEndPoint - * changing state between being idle and not idle. - */ - typedef void (*OnTCPSendIdleChangedFunct)(TCPEndPoint *endPoint, bool isIdle); - - /** The event handling function delegate of the endpoint signaling when the - * idleness of the TCP connection's send channel changes. This is utilized - * by upper layers to take appropriate actions based on whether sent data - * has been reliably delivered to the peer. */ - OnTCPSendIdleChangedFunct OnTCPSendIdleChanged; -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - -private: - static chip::System::ObjectPool sPool; - - chip::System::PacketBuffer *mRcvQueue; - chip::System::PacketBuffer *mSendQueue; -#if INET_TCP_IDLE_CHECK_INTERVAL > 0 - uint16_t mIdleTimeout; // in units of INET_TCP_IDLE_CHECK_INTERVAL; zero means no timeout - uint16_t mRemainingIdleTime; // in units of INET_TCP_IDLE_CHECK_INTERVAL -#endif // INET_TCP_IDLE_CHECK_INTERVAL > 0 - - uint32_t mConnectTimeoutMsecs; // This is the timeout to wait for a Connect call to succeed or - // return an error; zero means use system defaults. - -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - uint32_t mUserTimeoutMillis; // The configured TCP user timeout value in milliseconds. - // If 0, assume not set. -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - bool mIsTCPSendIdle; // Indicates whether the send channel of the TCPEndPoint is Idle. - - uint16_t mTCPSendQueueRemainingPollCount; // The current remaining number of TCP SendQueue polls before - // the TCP User timeout period is reached. - - uint32_t mTCPSendQueuePollPeriodMillis; // The configured period of active polling of the TCP - // SendQueue. If 0, assume not set. - void SetTCPSendIdleAndNotifyChange(bool aIsSendIdle); - -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - - bool mUserTimeoutTimerRunning; // Indicates whether the TCP UserTimeout timer has been started. - - static void TCPUserTimeoutHandler(chip::System::Layer* aSystemLayer, void* aAppState, chip::System::Error aError); - - void StartTCPUserTimeoutTimer(void); - - void StopTCPUserTimeoutTimer(void); - - void RestartTCPUserTimeoutTimer(void); - - void ScheduleNextTCPUserTimeoutPoll(uint32_t aTimeOut); - -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - uint16_t MaxTCPSendQueuePolls(void); -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - uint32_t mBytesWrittenSinceLastProbe; // This counts the number of bytes written on the TCP socket since the - // last probe into the TCP outqueue was made. - - uint32_t mLastTCPKernelSendQueueLen; // This is the measured size(in bytes) of the kernel TCP send queue - // at the end of the last user timeout window. - INET_ERROR CheckConnectionProgress(bool &IsProgressing); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - - TCPEndPoint(void); // not defined - TCPEndPoint(const TCPEndPoint&); // not defined - ~TCPEndPoint(void); // not defined - - void Init(InetLayer *inetLayer); - INET_ERROR DriveSending(void); - void DriveReceiving(void); - void HandleConnectComplete(INET_ERROR err); - void HandleAcceptError(INET_ERROR err); - INET_ERROR DoClose(INET_ERROR err, bool suppressCallback); - static bool IsConnected(int state); - - static void TCPConnectTimeoutHandler(chip::System::Layer* aSystemLayer, void* aAppState, chip::System::Error aError); - - void StartConnectTimerIfSet(void); - void StopConnectTimer(void); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - chip::System::PacketBuffer *mUnsentQueue; - uint16_t mUnsentOffset; - - INET_ERROR GetPCB(IPAddressType addrType); - void HandleDataSent(uint16_t len); - void HandleDataReceived(chip::System::PacketBuffer *buf); - void HandleIncomingConnection(TCPEndPoint *pcb); - void HandleError(INET_ERROR err); - - static err_t LwIPHandleConnectComplete(void *arg, struct tcp_pcb *tpcb, err_t lwipErr); - static err_t LwIPHandleIncomingConnection(void *arg, struct tcp_pcb *tcpConPCB, err_t lwipErr); - static err_t LwIPHandleDataReceived(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); - static err_t LwIPHandleDataSent(void *arg, struct tcp_pcb *tpcb, u16_t len); - static void LwIPHandleError(void *arg, err_t err); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - INET_ERROR GetSocket(IPAddressType addrType); - SocketEvents PrepareIO(void); - void HandlePendingIO(void); - void ReceiveData(void); - void HandleIncomingConnection(void); - INET_ERROR BindSrcAddrFromIntf(IPAddressType addrType, InterfaceId intf); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -}; - -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS && INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT -inline uint16_t TCPEndPoint::MaxTCPSendQueuePolls(void) -{ - // If the UserTimeout is configured less than or equal to the poll interval, - // return 1 to poll at least once instead of returning zero and timing out - // immediately. - return (mUserTimeoutMillis > mTCPSendQueuePollPeriodMillis) ? - (mUserTimeoutMillis / mTCPSendQueuePollPeriodMillis) : 1; -} -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS && INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - -inline bool TCPEndPoint::IsConnected(void) const -{ - return IsConnected(State); -} - -inline uint16_t TCPEndPoint::LogId(void) -{ - return static_cast(reinterpret_cast(this)); -} - -inline void TCPEndPoint::MarkActive(void) -{ -#if INET_TCP_IDLE_CHECK_INTERVAL > 0 - mRemainingIdleTime = mIdleTimeout; -#endif // INET_TCP_IDLE_CHECK_INTERVAL > 0 -} - -} // namespace Inet -} // namespace chip - -#endif // !defined(TCPENDPOINT_H) diff --git a/src/inet/TunEndPoint.cpp b/src/inet/TunEndPoint.cpp deleted file mode 100644 index 4a4f2cbd88ac84..00000000000000 --- a/src/inet/TunEndPoint.cpp +++ /dev/null @@ -1,812 +0,0 @@ -/* - * - * - * - * 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 implements the TunnelEndPoint abstraction APIs in the Inet - * Layer for creation and management of tunnel interfaces instantiated - * within either Linux Sockets or LwIP. - * - */ - -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif - -#include "TunEndPoint.h" -#include - -#include -#include - -#include -#include - -#include "arpa-inet-compatibility.h" - -namespace chip { -namespace Inet { - -using chip::System::PacketBuffer; - -chip::System::ObjectPool TunEndPoint::sPool; - -using namespace chip::Encoding; - -/** - * Initialize the Tunnel EndPoint object. - * - * @note - * By convention, the \c Init method on \c EndPointBasis - * subclasses is \c private. It should not be used outside \c InetLayer. - * - * @param[in] inetLayer A pointer to the Inet layer object that - * created the Tunnel EndPoint. - * - */ -void TunEndPoint::Init(InetLayer *inetLayer) -{ - InitEndPointBasis(*inetLayer); -} - -/** - * Open a tunnel pseudo interface and create a handle to it. - * - * @note - * This method has different signatures on LwIP systems and - * POSIX systems. On LwIP, there is an argument for specifying the name - * of the tunnel interface. On POSIX, the method has no arguments and the - * name of the tunnel device is implied. - * - * @return INET_NO_ERROR on success, else a corresponding INET mapped OS error. - */ -#if CHIP_SYSTEM_CONFIG_USE_LWIP -INET_ERROR TunEndPoint::Open (void) -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -INET_ERROR TunEndPoint::Open (const char *intfName) -#endif //CHIP_SYSTEM_CONFIG_USE_SOCKETS -{ - INET_ERROR err = INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - struct netif *tNetif = NULL; - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - tNetif = netif_add(&mTunNetIf, NULL, NULL, NULL, this, TunInterfaceNetifInit, tcpip_input); - - // UnLock LwIP stack - UNLOCK_TCPIP_CORE(); - - VerifyOrExit(tNetif != NULL, err = INET_ERROR_INTERFACE_INIT_FAILURE); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - //Create the tunnel device - err = TunDevOpen(intfName); - SuccessOrExit(err); - - printf("Opened tunnel device: %s\n", intfName); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (err == INET_NO_ERROR) - mState = kState_Open; - -exit: - - return err; -} - -/** - * Close the tunnel pseudo interface device. - * - */ -void TunEndPoint::Close (void) -{ - if (mState != kState_Closed) - { - - // For LwIP, we do not remove the netif as it would have - // an impact on the interface iterator in chip which - // might lose reference to a particular netif index that - // it might be holding on to. -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - if (mSocket >= 0) - { - chip::System::Layer& lSystemLayer = SystemLayer(); - - // Wake the thread calling select so that it recognizes the socket is closed. - lSystemLayer.WakeSelect(); - TunDevClose(); - } - - // Clear any results from select() that indicate pending I/O for the socket. - mPendingIO.Clear(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - mState = kState_Closed; - } -} - -/** - * Close the tunnel pseudo interface device and decrement the reference count - * of the InetLayer object. - * - */ -void TunEndPoint::Free() -{ - Close(); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - DeferredFree(kReleaseDeferralErrorTactic_Release); -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP - Release(); -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP -} - -/** - * Send an IPv6 packet to the tun device to be sent out. - * - * @note - * This method performs a couple of minimal sanity checks on the packet to - * be sure it is IP version 6 then dispatches it for encapsulation in a - * chip tunneling message. - * - * @param[in] message the IPv6 packet to send. - * - * @retval INET_NO_ERROR success: packet encapsulated and queued to send - * @retval INET_ERROR_NOT_SUPPORTED packet not IP version 6 - * @retval INET_ERROR_BAD_ARGS \c message is a \c NULL pointer - * - */ -INET_ERROR TunEndPoint::Send (PacketBuffer *msg) -{ - INET_ERROR ret = INET_NO_ERROR; - - ret = CheckV6Sanity(msg); - - if (ret == INET_NO_ERROR) - { - ret = TunDevSendMessage(msg); - } - - return ret; -} - -/** - * Extract the activation state of the tunnel interface. - * - * @returns \c true if the tunnel interface is active, - * otherwise \c false. - */ -bool TunEndPoint::IsInterfaceUp (void) const -{ - bool ret = false; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - ret = netif_is_up(&mTunNetIf); - - // UnLock LwIP stack - UNLOCK_TCPIP_CORE(); - - ExitNow(); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - int sockfd = INET_INVALID_SOCKET_FD; - struct ::ifreq ifr; - - memset(&ifr, 0, sizeof(ifr)); - - //Get interface - if (TunGetInterface(mSocket, &ifr) < 0) - { - ExitNow(); - } - - sockfd = socket(AF_INET6, SOCK_DGRAM | NL_SOCK_CLOEXEC, IPPROTO_IP); - if (sockfd < 0) - { - ExitNow(); - } - - //Get interface flags - if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) - { - ExitNow(); - } - - ret = ((ifr.ifr_flags & IFF_UP) == IFF_UP); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -exit: -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - if (sockfd >= 0) - { - close(sockfd); - } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return ret; -} - -/** - * Activate the tunnel interface. - * - * @retval INET_NO_ERROR success: tunnel interface is activated. - * @retval other another system or platform error - */ -INET_ERROR TunEndPoint::InterfaceUp (void) -{ - INET_ERROR err = INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - netif_set_up(&mTunNetIf); - - // UnLock LwIP stack - UNLOCK_TCPIP_CORE(); - - ExitNow(); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - int sockfd = INET_INVALID_SOCKET_FD; - struct ::ifreq ifr; - - memset(&ifr, 0, sizeof(ifr)); - - //Get interface - if (TunGetInterface(mSocket, &ifr) < 0) - { - ExitNow(err = chip::System::MapErrorPOSIX(errno)); - } - - sockfd = socket(AF_INET6, SOCK_DGRAM | NL_SOCK_CLOEXEC, IPPROTO_IP); - if (sockfd < 0) - { - ExitNow(err = chip::System::MapErrorPOSIX(errno)); - } - - //Get interface flags - if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) - { - ExitNow(err = chip::System::MapErrorPOSIX(errno)); - } - - //Set flag to activate interface - ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); - if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) - { - err = chip::System::MapErrorPOSIX(errno); - } - - //Set the MTU - ifr.ifr_mtu = CHIP_CONFIG_TUNNEL_INTERFACE_MTU; - if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) - { - ExitNow(err = chip::System::MapErrorPOSIX(errno)); - } - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -exit: -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - if (sockfd >= 0) - { - close(sockfd); - } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return err; -} - -/** - * @brief Deactivate the tunnel interface. - * - * @retval INET_NO_ERROR success: tunnel interface is deactivated. - * @retval other another system or platform error - */ -INET_ERROR TunEndPoint::InterfaceDown (void) -{ - INET_ERROR err = INET_NO_ERROR; -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - int sockfd = INET_INVALID_SOCKET_FD; - struct ::ifreq ifr; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - //Remove the link local address from the netif - memset(&(mTunNetIf.ip6_addr[0]), 0, sizeof(ip6_addr_t)); - - netif_set_down(&mTunNetIf); - - // UnLock LwIP stack - UNLOCK_TCPIP_CORE(); - - ExitNow(); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - memset(&ifr, 0, sizeof(ifr)); - - //Get interface - if (TunGetInterface(mSocket, &ifr) < 0) - { - ExitNow(err = chip::System::MapErrorPOSIX(errno)); - } - - sockfd = socket(AF_INET6, SOCK_DGRAM | NL_SOCK_CLOEXEC, IPPROTO_IP); - if (sockfd < 0) - { - ExitNow(err = chip::System::MapErrorPOSIX(errno)); - } - - //Get interface flags - if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) - { - ExitNow(err = chip::System::MapErrorPOSIX(errno)); - } - - //Set flag to deactivate interface - ifr.ifr_flags &= ~(IFF_UP); - if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) - { - err = chip::System::MapErrorPOSIX(errno); - } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -exit: -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - if (sockfd >= 0) - { - close(sockfd); - } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - return err; -} - -/** - * @brief Get the tunnel interface identifier. - * - * @return The tunnel interface identifier. - */ -InterfaceId TunEndPoint::GetTunnelInterfaceId(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_LWIP - return &mTunNetIf; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - INET_ERROR err = INET_NO_ERROR; - InterfaceId tunIntfId = INET_NULL_INTERFACEID; - const char *tunIntfPtr = &tunIntfName[0]; - - err = InterfaceNameToId(tunIntfPtr, tunIntfId); - if (err != INET_NO_ERROR) - { - tunIntfId = INET_NULL_INTERFACEID; - } - - return tunIntfId; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -/* Function for sending the IPv6 packets over LwIP */ -INET_ERROR TunEndPoint::TunDevSendMessage(PacketBuffer *msg) -{ - INET_ERROR ret = INET_NO_ERROR; - struct pbuf *p = NULL; - err_t err = ERR_OK; - - // no packet could be read, silently ignore this - VerifyOrExit(msg != NULL, ret = INET_ERROR_BAD_ARGS); - - p = (struct pbuf *)msg; - - //Call the input function for the netif object in LWIP. - //This essentially creates a TCP_IP msg and puts into - //the mbox message queue for processing by the TCP/IP - //stack. - - if ((err = tcpip_input(p, &mTunNetIf)) != ERR_OK) - { - LWIP_DEBUGF(NETIF_DEBUG, ("tunNetif_input: IP input error\n")); - ExitNow(ret = chip::System::MapErrorLwIP(err)); - } - -exit: - return (ret); -} -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -/* Function for sending the IPv6 packets over Linux sockets */ -INET_ERROR TunEndPoint::TunDevSendMessage(PacketBuffer *msg) -{ - INET_ERROR ret = INET_NO_ERROR; - ssize_t lenSent = 0; - uint8_t *p = NULL; - - // no packet could be read, silently ignore this - VerifyOrExit(msg != NULL, ret = INET_ERROR_BAD_ARGS); - - p = msg->Start(); - - lenSent = write(mSocket, p, msg->DataLength()); - if (lenSent < 0) - { - ExitNow(ret = chip::System::MapErrorPOSIX(errno)); - } - else if (lenSent < msg->DataLength()) - { - ExitNow(ret = INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED); - } - -exit: - if (msg != NULL) - { - PacketBuffer::Free(msg); - } - - return (ret); -} -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/* Function that performs some basic sanity checks for IPv6 packets */ -INET_ERROR TunEndPoint::CheckV6Sanity (PacketBuffer *msg) -{ - INET_ERROR err = INET_NO_ERROR; - uint8_t *p = NULL; - struct ip6_hdr *ip6hdr = NULL; - - p = msg->Start(); - - ip6hdr = (struct ip6_hdr *)p; - - VerifyOrExit(ip6hdr != NULL, err = INET_ERROR_BAD_ARGS); - - //Do some IPv6 sanity checks -#if CHIP_SYSTEM_CONFIG_USE_LWIP - if (IP6H_V(ip6hdr) != 6) -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - if ((ip6hdr->ip6_vfc >> 4) != 6) -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - { - ExitNow(err = INET_ERROR_NOT_SUPPORTED); - } - -exit: - - return err; -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -/* Handler to send received packet to upper layer callback */ -void TunEndPoint::HandleDataReceived (PacketBuffer *msg) -{ - INET_ERROR err = INET_NO_ERROR; - if (mState == kState_Open && OnPacketReceived != NULL) - { - err = CheckV6Sanity(msg); - if (err == INET_NO_ERROR) - { - OnPacketReceived(this, msg); - } - else - { - if (OnReceiveError != NULL) - { - OnReceiveError(this, err); - } - - PacketBuffer::Free(msg); - } - } - else - { - PacketBuffer::Free(msg); - } -} - -/* Post an event to the Inet layer event queue from LwIP */ -err_t TunEndPoint::LwIPPostToInetEventQ (struct netif *netif, struct pbuf *p) -{ - err_t lwipErr = ERR_OK; - INET_ERROR err = INET_NO_ERROR; - TunEndPoint* ep = static_cast(netif->state); - chip::System::Layer& lSystemLayer = ep->SystemLayer(); - PacketBuffer* buf = PacketBuffer::NewWithAvailableSize(p->tot_len); - - // Starting off with a reserved size of the default CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE - // which allows for adding the chip header and the underlying transport and IP headers - // encapsulating this tunneled packet. - - VerifyOrExit(buf != NULL, lwipErr = ERR_MEM); - - buf->SetDataLength(p->tot_len); - - // Make a pbuf alloc and copy to post to Inetlayer queue because LwIP would free the - // passed pbuf as it made a down-call to send it out the tunnel netif. - - lwipErr = pbuf_copy((struct pbuf *)buf, p); - VerifyOrExit(lwipErr == ERR_OK, (void)lwipErr); - - err = lSystemLayer.PostEvent(*ep, kInetEvent_TunDataReceived, (uintptr_t)buf); - VerifyOrExit(err == INET_NO_ERROR, lwipErr = ERR_MEM); - - buf = NULL; - -exit: - if (buf != NULL) - { - PacketBuffer::Free(buf); - } - - return lwipErr; -} - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -#if LWIP_IPV4 -/* Output handler for netif */ -err_t TunEndPoint::LwIPOutputIPv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) -{ - LWIP_UNUSED_ARG(addr); - - return LwIPPostToInetEventQ(netif, p); -} -#endif // LWIP_IPV4 - -#if LWIP_IPV6 -/* Output handler for netif */ -err_t TunEndPoint::LwIPOutputIPv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) -{ - LWIP_UNUSED_ARG(addr); - - return LwIPPostToInetEventQ(netif, p); -} -#endif // LWIP_IPV4 -#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 -/* Receive message in LwIP */ -err_t TunEndPoint::LwIPReceiveTunMessage (struct netif *netif, struct pbuf *p, ip4_addr_t *addr) -{ - LWIP_UNUSED_ARG(addr); - - return LwIPPostToInetEventQ(netif, p); -} - -#if LWIP_IPV6 -err_t TunEndPoint::LwIPReceiveTunV6Message (struct netif *netif, struct pbuf *p, ip6_addr_t *addr) -{ - LWIP_UNUSED_ARG(addr); - - return LwIPPostToInetEventQ(netif, p); -} -#endif // LWIP_IPV6 -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 - -/* Initialize the LwIP tunnel netif interface */ -err_t TunEndPoint::TunInterfaceNetifInit (struct netif *netif) -{ - netif->name[0] = 't'; - netif->name[1] = 'n'; -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -#if LWIP_IPV4 - netif->output = LwIPOutputIPv4; -#endif /* LWIP_IPV6 */ -#if LWIP_IPV6 - netif->output_ip6 = LwIPOutputIPv6; -#endif /* LWIP_IPV6 */ -#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 - netif->output = LwIPReceiveTunMessage; -#if LWIP_IPV6 - netif->output_ip6 = LwIPReceiveTunV6Message; -#endif /* LWIP_IPV6 */ -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 - netif->linkoutput = NULL; - - netif->mtu = CHIP_CONFIG_TUNNEL_INTERFACE_MTU; - - netif->hwaddr_len = 6; - memset(netif->hwaddr, 0, NETIF_MAX_HWADDR_LEN); - netif->hwaddr[5] = 1; - -#if LWIP_VERSION_MAJOR == 1 && LWIP_VERSION_MINOR < 5 - /* device capabilities */ - netif->flags |= NETIF_FLAG_POINTTOPOINT; -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - - return ERR_OK; -} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -/* Open a tun device in linux */ -INET_ERROR TunEndPoint::TunDevOpen (const char *intfName) -{ - struct ::ifreq ifr; - int fd = INET_INVALID_SOCKET_FD; - INET_ERROR ret = INET_NO_ERROR; - - if ((fd = open(INET_CONFIG_TUNNEL_DEVICE_NAME, O_RDWR | NL_O_CLOEXEC)) < 0) - { - ExitNow(ret = chip::System::MapErrorPOSIX(errno)); - } - - //Keep copy of open device fd - mSocket = fd; - - memset(&ifr, 0, sizeof(ifr)); - - ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - - if (*intfName) - { - strncpy(ifr.ifr_name, intfName, sizeof(ifr.ifr_name) - 1); - } - - if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) - { - ExitNow(ret = chip::System::MapErrorPOSIX(errno)); - } - - //Verify name - memset(&ifr, 0, sizeof(ifr)); - if (TunGetInterface(fd, &ifr) < 0) - { - ExitNow(ret = chip::System::MapErrorPOSIX(errno)); - } - - if (ifr.ifr_name[0] != '\0') - { - //Keep member copy of interface name and Id - strncpy(tunIntfName, ifr.ifr_name, sizeof(tunIntfName) - 1); - } - else - { - ExitNow(ret = chip::System::MapErrorPOSIX(errno)); - } - -exit: - - if (ret != INET_NO_ERROR) - { - TunDevClose(); - } - - return ret; -} - -/* Close a tun device */ -void TunEndPoint::TunDevClose (void) -{ - if (mSocket >= 0) - { - close(mSocket); - } - mSocket = INET_INVALID_SOCKET_FD; -} - -/* Get the tun device interface in Linux */ -int TunEndPoint::TunGetInterface (int fd, - struct ::ifreq *ifr) -{ - return ioctl(fd, TUNGETIFF, (void*)ifr); -} - -/* Read packets from TUN device in Linux */ -INET_ERROR TunEndPoint::TunDevRead (PacketBuffer *msg) -{ - ssize_t rcvLen; - INET_ERROR err = INET_NO_ERROR; - uint8_t *p = NULL; - p = msg->Start(); - - rcvLen = read(mSocket, p, msg->AvailableDataLength()); - if (rcvLen < 0) - { - err = chip::System::MapErrorPOSIX(errno); - } - else if (rcvLen > msg->AvailableDataLength()) - { - err = INET_ERROR_INBOUND_MESSAGE_TOO_BIG; - } - else - { - msg->SetDataLength((uint16_t)rcvLen); - } - - return err; -} - -/* Prepare socket for reading */ -SocketEvents TunEndPoint::PrepareIO () -{ - SocketEvents res; - - if (mState == kState_Open && OnPacketReceived != NULL) - { - res.SetRead(); - } - - return res; -} - -/* Read from the Tun device in Linux and pass up to upper layer callback */ -void TunEndPoint::HandlePendingIO () -{ - INET_ERROR err = INET_NO_ERROR; - - if (mState == kState_Open && OnPacketReceived != NULL && mPendingIO.IsReadable()) - { - - PacketBuffer *buf = PacketBuffer::New(0); - - if (buf != NULL) - { - //Read data from Tun Device - err = TunDevRead(buf); - if (err == INET_NO_ERROR) - { - err = CheckV6Sanity(buf); - } - } - else - { - err = INET_ERROR_NO_MEMORY; - } - - if (err == INET_NO_ERROR) - { - OnPacketReceived(this, buf); - } - else - { - PacketBuffer::Free(buf); - if (OnReceiveError != NULL) - { - OnReceiveError(this, err); - } - } - } - - mPendingIO.Clear(); -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -} // namespace Inet -} // namespace chip diff --git a/src/inet/TunEndPoint.h b/src/inet/TunEndPoint.h deleted file mode 100644 index db95f4f3591d30..00000000000000 --- a/src/inet/TunEndPoint.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * - * - * - * 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 header file defines the Inet::TunEndPoint class, where - * the Nest Inet Layer encapsulates its foundational logic for the chip - * tunneling agent. - */ - -#ifndef TUNENDPOINT_H -#define TUNENDPOINT_H - -#include -#include -#include "IPPrefix.h" - -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include "lwip/netif.h" -#include -#include -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include -#include -#include -#include -#include -#include -#include -#include - -#if HAVE_LINUX_IF_TUN_H -#include -#endif // HAVE_LINUX_IF_TUN_H - -#if HAVE_LINUX_ROUTE_H -#include -#endif // HAVE_LINUX_ROUTE_H - -#if HAVE_LINUX_IPV6_ROUTE_H -#include -#endif // HAVE_LINUX_IPV6_ROUTE_H -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -/** Define portable flags for closing file descriptor upon - * inheritance by an external sub-process. This is only a - * safety guard. Code that spawns a child process must make - * sure that any unneeded inherited file descriptor is closed. - */ -#ifdef O_CLOEXEC -#define NL_O_CLOEXEC O_CLOEXEC -#else -#define NL_O_CLOEXEC 0 -#endif - -#ifdef SOCK_CLOEXEC -#define NL_SOCK_CLOEXEC SOCK_CLOEXEC -#else -#define NL_SOCK_CLOEXEC 0 -#endif - -namespace chip { -namespace Inet { - -class InetLayer; -class IPPacketInfo; - -/** - * @brief Objects of this class represent tunnel interfaces. - * - * @details - * Nest Inet Layer encapsulates methods for interacting on both POSIX systems - * and LwIP systems with an IP-in-IP tunneling mechanism for supporting the - * chip tunnel agent. - */ -class DLL_EXPORT TunEndPoint: public EndPointBasis -{ - friend class InetLayer; - -public: - - /** - * @brief Basic dynamic state of the underlying tunnel. - * - * @details - * Objects are initialized in the "open" state, proceed to the "closed" - * state when they are ready to be recycled. - */ - enum - { - kState_Open = 0, - kState_Closed = 1 - } mState; - - /** - * @brief Operation when setting route to tunnel interface. - * - * @details - * Values of this enumerated type are used when setting a route for the - * encapsulated tunnel. - */ - typedef enum RouteOp - { - kRouteTunIntf_Add = 0, /**< Add route for a prefix. */ - kRouteTunIntf_Del = 1 /**< Remove route for a prefix. */ - } RouteOp; - - /** Pointer to application-specific state object. */ - void *mAppState; - - void Init(InetLayer *inetLayer); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - INET_ERROR Open(void); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - INET_ERROR Open(const char *intfName); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - /** Close the tunnel and release handle on the object. */ - void Free(void); - - INET_ERROR Send(chip::System::PacketBuffer *message); - - bool IsInterfaceUp(void) const; - - INET_ERROR InterfaceUp(void); - - INET_ERROR InterfaceDown(void); - - /** - * @brief Type of packet receive event handler. - * - * @details - * Type of delegate to a higher layer to act upon receipt of an IPv6 - * packet from the tunnel. - * - * @param[in] endPoint A pointer to the TunEndPoint object. - * @param[in] message A pointer to the chip::System::PacketBuffer message object. - */ - typedef void (*OnPacketReceivedFunct)(TunEndPoint *endPoint, chip::System::PacketBuffer *message); - - /** The endpoint's packet receive event handler delegate. */ - OnPacketReceivedFunct OnPacketReceived; - - /** - * @brief Type of error event handler. - * - * @details - * Type of delegate to a higher layer to act upon error processing an IPv6 - * packet from the tunnel. - * - * @param[in] endPoint The TunEndPoint object. - * @param[in] err Error code reported. - */ - typedef void (*OnReceiveErrorFunct)(TunEndPoint *endPoint, INET_ERROR err); - OnReceiveErrorFunct OnReceiveError; - - InterfaceId GetTunnelInterfaceId(void); - -private: - - TunEndPoint(void); // not defined - TunEndPoint(const TunEndPoint&); // not defined - ~TunEndPoint(void); // not defined - - static chip::System::ObjectPool sPool; - - /** Close the tunnel. */ - void Close(void); - - // Function that performs some sanity tests for IPv6 packets. - INET_ERROR CheckV6Sanity(chip::System::PacketBuffer *message); - // Function for sending the IPv6 packets over Linux sockets or LwIP. - INET_ERROR TunDevSendMessage(chip::System::PacketBuffer *msg); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - // Network interface structure holding the tunnel interface in LwIP. - struct netif mTunNetIf; - - INET_ERROR TunDevOpen(void); - void HandleDataReceived(chip::System::PacketBuffer *msg); - - static err_t LwIPPostToInetEventQ(struct netif *netif, struct pbuf *p); -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -#if LWIP_IPV4 - static err_t LwIPOutputIPv4(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr); -#endif // LWIP_IPV4 -#if LWIP_IPV6 - static err_t LwIPOutputIPv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr); -#endif // LWIP_IPV6 -#else // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 - static err_t LwIPReceiveTunMessage(struct netif *netif, struct pbuf *p, ip4_addr_t *addr); -#if LWIP_IPV6 - static err_t LwIPReceiveTunV6Message(struct netif *netif, struct pbuf *p, ip6_addr_t *addr); -#endif // LWIP_IPV6 -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR < 5 - static err_t TunInterfaceNetifInit(struct netif *netif); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - //Tunnel interface name - char tunIntfName[IFNAMSIZ]; - - INET_ERROR TunDevOpen(const char *interfaceName); - void TunDevClose(void); - INET_ERROR TunDevRead(chip::System::PacketBuffer *msg); - static int TunGetInterface(int fd, struct ::ifreq *ifr); - - SocketEvents PrepareIO(void); - void HandlePendingIO(void); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -}; - -} // namespace Inet -} // namespace chip - -#endif // !defined(TUNENDPOINT_H) diff --git a/src/inet/UDPEndPoint.cpp b/src/inet/UDPEndPoint.cpp deleted file mode 100644 index 4b6f8f338f814e..00000000000000 --- a/src/inet/UDPEndPoint.cpp +++ /dev/null @@ -1,934 +0,0 @@ -/* - * - * - * - * 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 implements the Inet::UDPEndPoint - * class, where the Nest Inet Layer encapsulates methods for - * interacting with UDP transport endpoints (SOCK_DGRAM sockets - * on Linux and BSD-derived systems) or LwIP UDP protocol - * control blocks, as the system is configured accordingly. - * - */ - -#define __APPLE_USE_RFC_3542 - -#include - -#include "UDPEndPoint.h" -#include -#include "InetFaultInjection.h" -#include - -#include -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include -#if HAVE_SYS_SOCKET_H -#include -#endif // HAVE_SYS_SOCKET_H -#include -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#include "arpa-inet-compatibility.h" - -// SOCK_CLOEXEC not defined on all platforms, e.g. iOS/MacOS: -#ifdef SOCK_CLOEXEC -#define SOCK_FLAGS SOCK_CLOEXEC -#else -#define SOCK_FLAGS 0 -#endif - -namespace chip { -namespace Inet { - -using chip::System::PacketBuffer; - -chip::System::ObjectPool UDPEndPoint::sPool; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -/* - * Note that for LwIP InterfaceId is already defined to be 'struct - * netif'; consequently, some of the checking performed here could - * conceivably be optimized out and the HAVE_LWIP_UDP_BIND_NETIF case - * could simply be: - * - * udp_bind_netif(aUDP, intfId); - * - */ -static INET_ERROR LwIPBindInterface(struct udp_pcb *aUDP, InterfaceId intfId) -{ - INET_ERROR res = INET_NO_ERROR; - -#if HAVE_LWIP_UDP_BIND_NETIF - if (!IsInterfaceIdPresent(intfId)) - udp_bind_netif(aUDP, NULL); - else - { - struct netif *netifp = IPEndPointBasis::FindNetifFromInterfaceId(intfId); - - if (netifp == NULL) - res = INET_ERROR_UNKNOWN_INTERFACE; - else - udp_bind_netif(aUDP, netifp); - } -#else - if (!IsInterfaceIdPresent(intfId)) - aUDP->intf_filter = NULL; - else - { - struct netif *netifp = IPEndPointBasis::FindNetifFromInterfaceId(intfId); - - if (netifp == NULL) - res = INET_ERROR_UNKNOWN_INTERFACE; - else - aUDP->intf_filter = netifp; - } -#endif // HAVE_LWIP_UDP_BIND_NETIF - - return res; -} -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -/** - * @brief Bind the endpoint to an interface IP address. - * - * @param[in] addrType the protocol version of the IP address - * @param[in] addr the IP address (must be an interface address) - * @param[in] port the UDP port - * @param[in] intfId an optional network interface indicator - * - * @retval INET_NO_ERROR success: endpoint bound to address - * @retval INET_ERROR_INCORRECT_STATE endpoint has been bound previously - * @retval INET_NO_MEMORY insufficient memory for endpoint - * - * @retval INET_ERROR_UNKNOWN_INTERFACE - * On some platforms, the optionally specified interface is not - * present. - * - * @retval INET_ERROR_WRONG_PROTOCOL_TYPE - * \c addrType does not match \c IPVer. - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * \c addrType is \c kIPAddressType_Any, or the type of \c addr is not - * equal to \c addrType. - * - * @retval other another system or platform error - * - * @details - * Binds the endpoint to the specified network interface IP address. - * - * On LwIP, this method must not be called with the LwIP stack lock - * already acquired. - */ -INET_ERROR UDPEndPoint::Bind(IPAddressType addrType, IPAddress addr, uint16_t port, InterfaceId intfId) -{ - INET_ERROR res = INET_NO_ERROR; - - if (mState != kState_Ready && mState != kState_Bound) - { - res = INET_ERROR_INCORRECT_STATE; - goto exit; - } - - if ((addr != IPAddress::Any) && (addr.Type() != kIPAddressType_Any) && (addr.Type() != addrType)) - { - res = INET_ERROR_WRONG_ADDRESS_TYPE; - goto exit; - } - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Make sure we have the appropriate type of PCB. - res = GetPCB(addrType); - - // Bind the PCB to the specified address/port. - if (res == INET_NO_ERROR) - { -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - ip_addr_t ipAddr = addr.ToLwIPAddr(); -#if INET_CONFIG_ENABLE_IPV4 - lwip_ip_addr_type lType = IPAddress::ToLwIPAddrType(addrType); - IP_SET_TYPE_VAL(ipAddr, lType); -#endif // INET_CONFIG_ENABLE_IPV4 - res = chip::System::MapErrorLwIP(udp_bind(mUDP, &ipAddr, port)); -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - if (addrType == kIPAddressType_IPv6) - { - ip6_addr_t ipv6Addr = addr.ToIPv6(); - res = chip::System::MapErrorLwIP(udp_bind_ip6(mUDP, &ipv6Addr, port)); - } -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - { - ip4_addr_t ipv4Addr = addr.ToIPv4(); - res = chip::System::MapErrorLwIP(udp_bind(mUDP, &ipv4Addr, port)); - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - res = INET_ERROR_WRONG_ADDRESS_TYPE; -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - } - - if (res == INET_NO_ERROR) - { - res = LwIPBindInterface(mUDP, intfId); - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - SuccessOrExit(res); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - // Make sure we have the appropriate type of socket. - res = GetSocket(addrType); - SuccessOrExit(res); - - res = IPEndPointBasis::Bind(addrType, addr, port, intfId); - SuccessOrExit(res); - - mBoundPort = port; - mBoundIntfId = intfId; - - // If an ephemeral port was requested, retrieve the actual bound port. - if (port == 0) - { - union - { - struct sockaddr any; - struct sockaddr_in in; - struct sockaddr_in6 in6; - } boundAddr; - socklen_t boundAddrLen = sizeof(boundAddr); - - if (getsockname(mSocket, &boundAddr.any, &boundAddrLen) == 0) - { - if (boundAddr.any.sa_family == AF_INET) - { - mBoundPort = ntohs(boundAddr.in.sin_port); - } - else if (boundAddr.any.sa_family == AF_INET6) - { - mBoundPort = ntohs(boundAddr.in6.sin6_port); - } - } - } - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (res == INET_NO_ERROR) - { - mState = kState_Bound; - } - -exit: - return res; -} - -/** - * @brief Prepare the endpoint to receive UDP messages. - * - * @retval INET_NO_ERROR success: endpoint ready to receive messages. - * @retval INET_ERROR_INCORRECT_STATE endpoint is already listening. - * - * @details - * If \c State is already \c kState_Listening, then no operation is - * performed, otherwise the \c mState is set to \c kState_Listening and - * the endpoint is prepared to received UDP messages, according to the - * semantics of the platform. - * - * On LwIP, this method must not be called with the LwIP stack lock - * already acquired - */ -INET_ERROR UDPEndPoint::Listen(void) -{ - INET_ERROR res = INET_NO_ERROR; - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - chip::System::Layer& lSystemLayer = SystemLayer(); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (mState == kState_Listening) - { - res = INET_NO_ERROR; - goto exit; - } - - if (mState != kState_Bound) - { - res = INET_ERROR_INCORRECT_STATE; - goto exit; - } - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - udp_recv(mUDP, LwIPReceiveUDPMessage, this); -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - if (PCB_ISIPV6(mUDP)) - udp_recv_ip6(mUDP, LwIPReceiveUDPMessage, this); - else - udp_recv(mUDP, LwIPReceiveUDPMessage, this); -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - // Wake the thread calling select so that it starts selecting on the new socket. - lSystemLayer.WakeSelect(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (res == INET_NO_ERROR) - { - mState = kState_Listening; - } - - exit: - return res; -} - -/** - * @brief Close the endpoint. - * - * @details - * If mState != kState_Closed, then closes the endpoint, removing - * it from the set of endpoints eligible for communication events. - * - * On LwIP systems, this method must not be called with the LwIP stack - * lock already acquired. - */ -void UDPEndPoint::Close(void) -{ - if (mState != kState_Closed) - { -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Since UDP PCB is released synchronously here, but UDP endpoint itself might have to wait - // for destruction asynchronously, there could be more allocated UDP endpoints than UDP PCBs. - if (mUDP != NULL) - { - udp_remove(mUDP); - mUDP = NULL; - mLwIPEndPointType = kLwIPEndPointType_Unknown; - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (mSocket != INET_INVALID_SOCKET_FD) - { - chip::System::Layer& lSystemLayer = SystemLayer(); - - // Wake the thread calling select so that it recognizes the socket is closed. - lSystemLayer.WakeSelect(); - - close(mSocket); - mSocket = INET_INVALID_SOCKET_FD; - } - - // Clear any results from select() that indicate pending I/O for the socket. - mPendingIO.Clear(); - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - mState = kState_Closed; - } -} - -/** - * @brief Close the endpoint and recycle its memory. - * - * @details - * Invokes the \c Close method, then invokes the - * InetLayerBasis::Release method to return the object to its - * memory pool. - * - * On LwIP systems, this method must not be called with the LwIP stack - * lock already acquired. - */ -void UDPEndPoint::Free(void) -{ - Close(); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - DeferredFree(kReleaseDeferralErrorTactic_Die); -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP - Release(); -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP -} - -/** - * A synonym for SendTo(addr, port, INET_NULL_INTERFACEID, msg, sendFlags). - */ -INET_ERROR UDPEndPoint::SendTo(IPAddress addr, uint16_t port, chip::System::PacketBuffer *msg, uint16_t sendFlags) -{ - return SendTo(addr, port, INET_NULL_INTERFACEID, msg, sendFlags); -} - -/** - * @brief Send a UDP message to the specified destination address. - * - * @param[in] addr the destination IP address - * @param[in] port the destination UDP port - * @param[in] intfId an optional network interface indicator - * @param[in] msg the packet buffer containing the UDP message - * @param[in] sendFlags optional transmit option flags - * - * @retval INET_NO_ERROR success: \c msg is queued for transmit. - * - * @retval INET_ERROR_NOT_SUPPORTED - * the system does not support the requested operation. - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * the destination address and the bound interface address do not - * have matching protocol versions or address type. - * - * @retval INET_ERROR_MESSAGE_TOO_LONG - * \c msg does not contain the whole UDP message. - * - * @retval INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED - * On some platforms, only a truncated portion of \c msg was queued - * for transmit. - * - * @retval other - * another system or platform error - * - * @details - * If possible, then this method sends the UDP message \c msg to the - * destination \c addr (with \c intfId used as the scope - * identifier for IPv6 link-local destinations) and \c port with the - * transmit option flags encoded in \c sendFlags. - * - * Where (sendFlags & kSendFlag_RetainBuffer) != 0, calls - * chip::System::PacketBuffer::Free on behalf of the caller, otherwise this - * method deep-copies \c msg into a fresh object, and queues that for - * transmission, leaving the original \c msg available after return. - */ -INET_ERROR UDPEndPoint::SendTo(IPAddress addr, uint16_t port, InterfaceId intfId, chip::System::PacketBuffer *msg, uint16_t sendFlags) -{ - IPPacketInfo pktInfo; - pktInfo.Clear(); - pktInfo.DestAddress = addr; - pktInfo.DestPort = port; - pktInfo.Interface = intfId; - return SendMsg(&pktInfo, msg, sendFlags); -} - -/** - * @brief Send a UDP message to a specified destination. - * - * @param[in] pktInfo source and destination information for the UDP message - * @param[in] msg a packet buffer containing the UDP message - * @param[in] sendFlags optional transmit option flags - * - * @retval INET_NO_ERROR - * success: \c msg is queued for transmit. - * - * @retval INET_ERROR_NOT_SUPPORTED - * the system does not support the requested operation. - * - * @retval INET_ERROR_WRONG_ADDRESS_TYPE - * the destination address and the bound interface address do not - * have matching protocol versions or address type. - * - * @retval INET_ERROR_MESSAGE_TOO_LONG - * \c msg does not contain the whole UDP message. - * - * @retval INET_ERROR_OUTBOUND_MESSAGE_TRUNCATED - * On some platforms, only a truncated portion of \c msg was queued - * for transmit. - * - * @retval other - * another system or platform error - * - * @details - * Send the UDP message in \c msg to the destination address and port given in - * \c pktInfo. If \c pktInfo contains an interface id, the message will be sent - * over the specified interface. If \c pktInfo contains a source address, the - * given address will be used as the source of the UDP message. - * - * Where (sendFlags & kSendFlag_RetainBuffer) != 0, calls - * chip::System::PacketBuffer::Free on behalf of the caller, otherwise this - * method deep-copies \c msg into a fresh object, and queues that for - * transmission, leaving the original \c msg available after return. - */ -INET_ERROR UDPEndPoint::SendMsg(const IPPacketInfo *pktInfo, PacketBuffer *msg, uint16_t sendFlags) -{ - INET_ERROR res = INET_NO_ERROR; - const IPAddress & destAddr = pktInfo->DestAddress; - - INET_FAULT_INJECT(FaultInjection::kFault_Send, - if ((sendFlags & kSendFlag_RetainBuffer) == 0) - PacketBuffer::Free(msg); - return INET_ERROR_UNKNOWN_INTERFACE; - ); - INET_FAULT_INJECT(FaultInjection::kFault_SendNonCritical, - if ((sendFlags & kSendFlag_RetainBuffer) == 0) - PacketBuffer::Free(msg); - return INET_ERROR_NO_MEMORY; - ); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - if (sendFlags & kSendFlag_RetainBuffer) - { - // when retaining a buffer, the caller expects the msg to be - // unmodified. LwIP stack will normally prepend the packet - // headers as the packet traverses the UDP/IP/netif layers, - // which normally modifies the packet. We prepend a small - // pbuf to the beginning of the pbuf chain, s.t. all headers - // are added to the temporary space, just large enough to hold - // the transport headers. Careful reader will note: - // - // * we're actually oversizing the reserved space, the - // transport header is large enough for the TCP header which - // is larger than the UDP header, but it seemed cleaner than - // the combination of PBUF_IP for reserve space, UDP_HLEN - // for payload, and post allocation adjustment of the header - // space). - // - // * the code deviates from the existing PacketBuffer - // abstractions and needs to reach into the underlying pbuf - // code. The code in PacketBuffer also forces us to perform - // (effectively) a reinterpret_cast rather than a - // static_cast. JIRA WEAV-811 is filed to track the - // re-architecting of the memory management. - - pbuf *msgCopy = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM); - - if (msgCopy == NULL) - { - return INET_ERROR_NO_MEMORY; - } - - pbuf_chain(msgCopy, (pbuf *) msg); - msg = (PacketBuffer *)msgCopy; - } - - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Make sure we have the appropriate type of PCB based on the destination address. - res = GetPCB(destAddr.Type()); - SuccessOrExit(res); - - // Send the message to the specified address/port. - // If an outbound interface has been specified, call a specific version of the UDP sendto() - // function that accepts the target interface. - // If a source address has been specified, temporarily override the local_ip of the PCB. - // This results in LwIP using the given address being as the source address for the generated - // packet, as if the PCB had been bound to that address. - { - err_t lwipErr = ERR_VAL; - const IPAddress & srcAddr = pktInfo->SrcAddress; - const uint16_t & destPort = pktInfo->DestPort; - const InterfaceId & intfId = pktInfo->Interface; - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - - ip_addr_t lwipSrcAddr = srcAddr.ToLwIPAddr(); - ip_addr_t lwipDestAddr = destAddr.ToLwIPAddr(); - - ip_addr_t boundAddr; - ip_addr_copy(boundAddr, mUDP->local_ip); - - if (!ip_addr_isany(&lwipSrcAddr)) - { - ip_addr_copy(mUDP->local_ip, lwipSrcAddr); - } - - if (intfId != INET_NULL_INTERFACEID) - lwipErr = udp_sendto_if(mUDP, (pbuf *)msg, &lwipDestAddr, destPort, intfId); - else - lwipErr = udp_sendto(mUDP, (pbuf *)msg, &lwipDestAddr, destPort); - - ip_addr_copy(mUDP->local_ip, boundAddr); - -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - - ipX_addr_t boundAddr; - ipX_addr_copy(boundAddr, mUDP->local_ip); - - if (PCB_ISIPV6(mUDP)) - { - ip6_addr_t lwipSrcAddr = srcAddr.ToIPv6(); - ip6_addr_t lwipDestAddr = destAddr.ToIPv6(); - - if (!ip6_addr_isany(&lwipSrcAddr)) - { - ipX_addr_copy(mUDP->local_ip, *ip6_2_ipX(&lwipSrcAddr)); - } - - if (intfId != INET_NULL_INTERFACEID) - lwipErr = udp_sendto_if_ip6(mUDP, (pbuf *)msg, &lwipDestAddr, destPort, intfId); - else - lwipErr = udp_sendto_ip6(mUDP, (pbuf *)msg, &lwipDestAddr, destPort); - } - -#if INET_CONFIG_ENABLE_IPV4 - - else - { - ip4_addr_t lwipSrcAddr = srcAddr.ToIPv4(); - ip4_addr_t lwipDestAddr = destAddr.ToIPv4(); - ipX_addr_t boundAddr; - - if (!ip_addr_isany(&lwipSrcAddr)) - { - ipX_addr_copy(mUDP->local_ip, *ip_2_ipX(&lwipSrcAddr)); - } - - if (intfId != INET_NULL_INTERFACEID) - lwipErr = udp_sendto_if(mUDP, (pbuf *)msg, &lwipDestAddr, destPort, intfId); - else - lwipErr = udp_sendto(mUDP, (pbuf *)msg, &lwipDestAddr, destPort); - } - - ipX_addr_copy(mUDP->local_ip, boundAddr); - -#endif // INET_CONFIG_ENABLE_IPV4 -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - - if (lwipErr != ERR_OK) - res = chip::System::MapErrorLwIP(lwipErr); - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - PacketBuffer::Free(msg); -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - // Make sure we have the appropriate type of socket based on the - // destination address. - - res = GetSocket(destAddr.Type()); - SuccessOrExit(res); - - res = IPEndPointBasis::SendMsg(pktInfo, msg, sendFlags); - - if ((sendFlags & kSendFlag_RetainBuffer) == 0) - PacketBuffer::Free(msg); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -exit: - CHIP_SYSTEM_FAULT_INJECT_ASYNC_EVENT(); - - return res; -} - -/** - * @brief Bind the endpoint to a network interface. - * - * @param[in] addrType the protocol version of the IP address. - * - * @param[in] intf indicator of the network interface. - * - * @retval INET_NO_ERROR success: endpoint bound to address - * @retval INET_NO_MEMORY insufficient memory for endpoint - * @retval INET_ERROR_NOT_IMPLEMENTED system implementation not complete. - * - * @retval INET_ERROR_UNKNOWN_INTERFACE - * On some platforms, the interface is not present. - * - * @retval other another system or platform error - * - * @details - * Binds the endpoint to the specified network interface IP address. - * - * On LwIP, this method must not be called with the LwIP stack lock - * already acquired. - */ -INET_ERROR UDPEndPoint::BindInterface(IPAddressType addrType, InterfaceId intfId) -{ - INET_ERROR err = INET_NO_ERROR; - - if (mState != kState_Ready && mState != kState_Bound) - return INET_ERROR_INCORRECT_STATE; - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - - //A lock is required because the LwIP thread may be referring to intf_filter, - //while this code running in the Inet application is potentially modifying it. - //NOTE: this only supports LwIP interfaces whose number is no bigger than 9. - LOCK_TCPIP_CORE(); - - // Make sure we have the appropriate type of PCB. - err = GetPCB(addrType); - SuccessOrExit(err); - - err = LwIPBindInterface(mUDP, intfId); - - UNLOCK_TCPIP_CORE(); - - SuccessOrExit(err); - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - // Make sure we have the appropriate type of socket. - err = GetSocket(addrType); - SuccessOrExit(err); - - err = IPEndPointBasis::BindInterface(addrType, intfId); - SuccessOrExit(err); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (err == INET_NO_ERROR) - { - mState = kState_Bound; - } - -exit: - return err; -} - -void UDPEndPoint::Init(InetLayer *inetLayer) -{ - IPEndPointBasis::Init(inetLayer); -} - -/** - * Get the bound interface on this endpoint. - * - * @return InterfaceId The bound interface id. - */ -InterfaceId UDPEndPoint::GetBoundInterface(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if HAVE_LWIP_UDP_BIND_NETIF - return netif_get_by_index(mUDP->netif_idx); -#else - return mUDP->intf_filter; -#endif -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return mBoundIntfId; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -} - -uint16_t UDPEndPoint::GetBoundPort(void) -{ -#if CHIP_SYSTEM_CONFIG_USE_LWIP - return mUDP->local_port; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - return mBoundPort; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -} - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -void UDPEndPoint::HandleDataReceived(PacketBuffer *msg) -{ - IPEndPointBasis::HandleDataReceived(msg); -} - -INET_ERROR UDPEndPoint::GetPCB(IPAddressType addrType) -{ - INET_ERROR err = INET_NO_ERROR; - - // IMPORTANT: This method MUST be called with the LwIP stack LOCKED! - - // If a PCB hasn't been allocated yet... - if (mUDP == NULL) - { - // Allocate a PCB of the appropriate type. - if (addrType == kIPAddressType_IPv6) - { -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - mUDP = udp_new_ip_type(IPADDR_TYPE_V6); -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - mUDP = udp_new_ip6(); -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - } -#if INET_CONFIG_ENABLE_IPV4 - else if (addrType == kIPAddressType_IPv4) - { -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - mUDP = udp_new_ip_type(IPADDR_TYPE_V4); -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - mUDP = udp_new(); -#endif // LWIP_VERSION_MAJOR <= 1 || LWIP_VERSION_MINOR >= 5 - } -#endif // INET_CONFIG_ENABLE_IPV4 - else - { - ExitNow(err = INET_ERROR_WRONG_ADDRESS_TYPE); - } - - // Fail if the system has run out of PCBs. - if (mUDP == NULL) - { - chipLogError(Inet, "Unable to allocate UDP PCB"); - ExitNow(err = INET_ERROR_NO_MEMORY); - } - - // Allow multiple bindings to the same port. - ip_set_option(mUDP, SOF_REUSEADDR); - } - - // Otherwise, verify that the existing PCB is the correct type... - else - { - IPAddressType pcbAddrType; - - // Get the address type of the existing PCB. -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - switch (static_cast(IP_GET_TYPE(&mUDP->local_ip))) - { - case IPADDR_TYPE_V6: - pcbAddrType = kIPAddressType_IPv6; - break; -#if INET_CONFIG_ENABLE_IPV4 - case IPADDR_TYPE_V4: - pcbAddrType = kIPAddressType_IPv4; - break; -#endif // INET_CONFIG_ENABLE_IPV4 - default: - ExitNow(err = INET_ERROR_WRONG_ADDRESS_TYPE); - } -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 -#if INET_CONFIG_ENABLE_IPV4 - pcbAddrType = PCB_ISIPV6(mUDP) ? kIPAddressType_IPv6 : kIPAddressType_IPv4; -#else // !INET_CONFIG_ENABLE_IPV4 - pcbAddrType = kIPAddressType_IPv6; -#endif // !INET_CONFIG_ENABLE_IPV4 -#endif // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - - // Fail if the existing PCB is not the correct type. - VerifyOrExit(addrType == pcbAddrType, err = INET_ERROR_WRONG_ADDRESS_TYPE); - } - -exit: - return err; -} - -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -void UDPEndPoint::LwIPReceiveUDPMessage(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 -void UDPEndPoint::LwIPReceiveUDPMessage(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) -#endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -{ - UDPEndPoint* ep = static_cast(arg); - PacketBuffer* buf = reinterpret_cast(static_cast(p)); - chip::System::Layer& lSystemLayer = ep->SystemLayer(); - IPPacketInfo* pktInfo = NULL; - - pktInfo = GetPacketInfo(buf); - if (pktInfo != NULL) - { -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - pktInfo->SrcAddress = IPAddress::FromLwIPAddr(*addr); - pktInfo->DestAddress = IPAddress::FromLwIPAddr(*ip_current_dest_addr()); -#else // LWIP_VERSION_MAJOR <= 1 - if (PCB_ISIPV6(pcb)) - { - pktInfo->SrcAddress = IPAddress::FromIPv6(*(ip6_addr_t *)addr); - pktInfo->DestAddress = IPAddress::FromIPv6(*ip6_current_dest_addr()); - } -#if INET_CONFIG_ENABLE_IPV4 - else - { - pktInfo->SrcAddress = IPAddress::FromIPv4(*addr); - pktInfo->DestAddress = IPAddress::FromIPv4(*ip_current_dest_addr()); - } -#endif // INET_CONFIG_ENABLE_IPV4 -#endif // LWIP_VERSION_MAJOR <= 1 - - pktInfo->Interface = ip_current_netif(); - pktInfo->SrcPort = port; - pktInfo->DestPort = pcb->local_port; - } - - if (lSystemLayer.PostEvent(*ep, kInetEvent_UDPDataReceived, (uintptr_t)buf) != INET_NO_ERROR) - PacketBuffer::Free(buf); -} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -INET_ERROR UDPEndPoint::GetSocket(IPAddressType aAddressType) -{ - INET_ERROR lRetval = INET_NO_ERROR; - const int lType = (SOCK_DGRAM | SOCK_FLAGS); - const int lProtocol = 0; - - lRetval = IPEndPointBasis::GetSocket(aAddressType, lType, lProtocol); - SuccessOrExit(lRetval); - -exit: - return (lRetval); -} - -SocketEvents UDPEndPoint::PrepareIO(void) -{ - return (IPEndPointBasis::PrepareIO()); -} - -void UDPEndPoint::HandlePendingIO(void) -{ - if (mState == kState_Listening && OnMessageReceived != NULL && mPendingIO.IsReadable()) - { - const uint16_t lPort = mBoundPort; - - IPEndPointBasis::HandlePendingIO(lPort); - } - - mPendingIO.Clear(); -} - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - -} // namespace Inet -} // namespace chip diff --git a/src/inet/UDPEndPoint.h b/src/inet/UDPEndPoint.h deleted file mode 100644 index 63e6af7a7b3259..00000000000000 --- a/src/inet/UDPEndPoint.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * - * - * 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 header file defines the Inet::UDPEndPoint - * class, where the Nest Inet Layer encapsulates methods for - * interacting with UDP transport endpoints (SOCK_DGRAM sockets - * on Linux and BSD-derived systems) or LwIP UDP protocol - * control blocks, as the system is configured accordingly. - */ - -#ifndef UDPENDPOINT_H -#define UDPENDPOINT_H - -#include "IPEndPointBasis.h" -#include - -#include - -namespace chip { -namespace Inet { - -class InetLayer; -class IPPacketInfo; - -/** - * @brief Objects of this class represent UDP transport endpoints. - * - * @details - * Nest Inet Layer encapsulates methods for interacting with UDP transport - * endpoints (SOCK_DGRAM sockets on Linux and BSD-derived systems) or LwIP - * UDP protocol control blocks, as the system is configured accordingly. - */ - class DLL_EXPORT UDPEndPoint : public IPEndPointBasis -{ - friend class InetLayer; - -public: - INET_ERROR Bind(IPAddressType addrType, IPAddress addr, uint16_t port, InterfaceId intfId = INET_NULL_INTERFACEID); - INET_ERROR BindInterface(IPAddressType addrType, InterfaceId intf); - InterfaceId GetBoundInterface(void); - uint16_t GetBoundPort(void); - INET_ERROR Listen(void); - INET_ERROR SendTo(IPAddress addr, uint16_t port, chip::System::PacketBuffer *msg, uint16_t sendFlags = 0); - INET_ERROR SendTo(IPAddress addr, uint16_t port, InterfaceId intfId, chip::System::PacketBuffer *msg, uint16_t sendFlags = 0); - INET_ERROR SendMsg(const IPPacketInfo *pktInfo, chip::System::PacketBuffer *msg, uint16_t sendFlags = 0); - void Close(void); - void Free(void); - -private: - UDPEndPoint(void); // not defined - UDPEndPoint(const UDPEndPoint&); // not defined - ~UDPEndPoint(void); // not defined - - static chip::System::ObjectPool sPool; - - void Init(InetLayer *inetLayer); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP - void HandleDataReceived(chip::System::PacketBuffer *msg); - INET_ERROR GetPCB(IPAddressType addrType4); -#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 - static void LwIPReceiveUDPMessage(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); -#else // LWIP_VERSION_MAJOR <= 1 && LWIP_VERSION_MINOR < 5 - static void LwIPReceiveUDPMessage(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port); -#endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - uint16_t mBoundPort; - - INET_ERROR GetSocket(IPAddressType addrType); - SocketEvents PrepareIO(void); - void HandlePendingIO(void); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS -}; - -} // namespace Inet -} // namespace chip - -#endif // !defined(UDPENDPOINT_H) diff --git a/src/inet/arpa-inet-compatibility.h b/src/inet/arpa-inet-compatibility.h deleted file mode 100644 index 0dbc452e9ca3dc..00000000000000 --- a/src/inet/arpa-inet-compatibility.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * - * - * 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. - */ - -#ifndef ARPA_INET_COMPATIBILITY_H -#define ARPA_INET_COMPATIBILITY_H - -#include - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include - -#else // !CHIP_SYSTEM_CONFIG_USE_SOCKETS - -// NOTE WELL: when LWIP_VERSION_MAJOR == 1, LWIP_PREFIX_BYTEORDER_FUNCS instead of LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -#include -#include - -#if (defined(LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS) || defined(LWIP_PREFIX_BYTEORDER_FUNCS)) -#define htons(x) lwip_htons(x) -#define ntohs(x) lwip_ntohs(x) -#define htonl(x) lwip_htonl(x) -#define ntohl(x) lwip_ntohl(x) -#endif // (defined(LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS) || defined(LWIP_PREFIX_BYTEORDER_FUNCS)) - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#endif // !CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#endif // !defined(ARPA_INET_COMPATIBILITY_H) diff --git a/src/lib/core/CHIPEncoding.h b/src/lib/core/CHIPEncoding.h deleted file mode 100644 index ff01ea6b195131..00000000000000 --- a/src/lib/core/CHIPEncoding.h +++ /dev/null @@ -1,788 +0,0 @@ -/* - * - * - * - * 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 provides functions for: - * - *
    - *
  • Performing byte reordering by value for 16-, 32-, and 64-bit - * types.
  • - *
  • Safely performing simple, efficient memory-mapped - * accesses, potentially to unaligned memory locations, with or - * without byte reordering, to 8-, 16-, 32-, and 64-bit - * quantities, both with and without pointer management.
  • - *
- * - */ - -#ifndef _CHIPENCODING_H -#define _CHIPENCODING_H - -#include - -#include -#include -#include - -namespace chip { - -/** - * @namespace chip::Encoding - * - * This namespace provides functions for: - * - *
    - *
  • Performing byte reordering by value for 16-, 32-, and 64-bit - * types.
  • - *
  • Safely performing simple, efficient memory-mapped - * accesses, potentially to unaligned memory locations, with or - * without byte reordering, to 8-, 16-, 32-, and 64-bit - * quantities, both with and without pointer management.
  • - *
- * - */ -namespace Encoding { - -/** - * This unconditionally performs a byte order swap by value of the - * specified 16-bit value. - * - * @param[in] v The 16-bit value to be byte order swapped. - * - * @return The input value, byte order swapped. - */ -inline uint16_t Swap16(uint16_t v) { return nl::ByteOrder::Swap16(v); } - -/** - * This unconditionally performs a byte order swap by value of the - * specified 32-bit value. - * - * @param[in] v The 32-bit value to be byte order swapped. - * - * @return The input value, byte order swapped. - */ -inline uint32_t Swap32(uint32_t v) { return nl::ByteOrder::Swap32(v); } - -/** - * This unconditionally performs a byte order swap by value of the - * specified 64-bit value. - * - * @param[in] v The 64-bit value to be byte order swapped. - * - * @return The input value, byte order swapped. - */ -inline uint64_t Swap64(uint64_t v) { return nl::ByteOrder::Swap64(v); } - -/** - * Perform a, potentially unaligned, memory read of the 8-bit value - * from the specified pointer address. - * - * @param[in] p A pointer address, potentially unaligned, to read - * the 8-bit value from. - * - * @return The 8-bit value at the specified pointer address. - */ -inline uint8_t Get8(const uint8_t *p) { return nl::IO::Get8(p); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 8-bit value to the specified pointer address. - * - * @param[in] p A pointer address, potentially unaligned, to write - * the 8-bit value to. - * - * @param[in] v The 8-bit value to write. - * - */ -inline void Put8(uint8_t *p, uint8_t v) { nl::IO::Put8(p, v); } - -/** - * Perform a, potentially unaligned, memory read of the 16-bit value - * from the specified pointer address and increment the pointer by - * 8-bits (1 byte). - * - * @param[inout] p A reference to a pointer address, potentially - * unaligned, to read the 8-bit value from and to - * then increment by 8-bits (1 byte). - * - * @return The 8-bit value at the specified pointer address. - */ -inline uint8_t Read8(uint8_t *& p) { return nl::IO::Read8((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the 16-bit value - * from the specified pointer address and increment the pointer by - * 8-bits (1 byte). - * - * @param[inout] p A reference to a constant pointer address, - * potentially unaligned, to read the 8-bit value - * from and to then increment by 8-bits (1 byte). - * - * @return The 8-bit value at the specified pointer address. - */ -inline uint8_t Read8(const uint8_t *& p) { return nl::IO::Read8((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory write of the 8-bit value - * to the specified pointer address and increment the pointer by - * 8-bits (1 byte). - * - * @param[inout] p A reference to a pointer address, potentially - * unaligned, to read the 8-bit value from and to - * then increment by 8-bits (1 byte). - * - * @param[in] v The 8-bit value to write. - * - */ -inline void Write8(uint8_t *& p, uint8_t v) { *p++ = v; } - -/** - * @namespace chip::Encoding::LittleEndian - * - * This namespace provides functions for: - * - *
    - *
  • Performing byte reordering, relative to the host system, by - * value of little endian byte ordered values for 16-, 32-, and - * 64-bit types.
  • - *
  • Safely performing simple, efficient memory-mapped accesses, - * potentially to unaligned memory locations, with or without byte - * reordering, to 8-, 16-, 32-, and 64-bit little endian byte - * ordered quantities, both with and without pointer - * management.
  • - *
- * - * On little endian host systems no actual byte reordering will - * occur. On other systems, byte reordering is peformed as - * appropriate. - * - */ -namespace LittleEndian { - -/** - * This conditionally performs, as necessary for the target system, a - * byte order swap by value of the specified 16-bit value, presumed to - * be in little endian byte ordering to the target system (i.e. host) - * byte ordering. - * - * Consequently, on little endian target systems, this is a no-op and - * on big endian target systems, this performs a reordering. - * - * @param[in] v The 16-bit value to be byte order swapped. - * - * @return The input value, if necessary, byte order swapped. - */ -inline uint16_t HostSwap16(uint16_t v) { return nl::ByteOrder::Swap16LittleToHost(v); } - -/** - * This conditionally performs, as necessary for the target system, a - * byte order swap by value of the specified 32-bit value, presumed to - * be in little endian byte ordering to the target system (i.e. host) - * byte ordering. - * - * Consequently, on little endian target systems, this is a no-op and - * on big endian target systems, this performs a reordering. - * - * @param[in] v The 32-bit value to be byte order swapped. - * - * @return The input value, if necessary, byte order swapped. - */ -inline uint32_t HostSwap32(uint32_t v) { return nl::ByteOrder::Swap32LittleToHost(v); } - -/** - * This conditionally performs, as necessary for the target system, a - * byte order swap by value of the specified 64-bit value, presumed to - * be in little endian byte ordering to the target system (i.e. host) - * byte ordering. - * - * Consequently, on little endian target systems, this is a no-op and - * on big endian target systems, this performs a reordering. - * - * @param[in] v The 64-bit value to be byte order swapped. - * - * @return The input value, if necessary, byte order swapped. - */ -inline uint64_t HostSwap64(uint64_t v) { return nl::ByteOrder::Swap64LittleToHost(v); } - -/** - * Perform a, potentially unaligned, memory read of the little endian - * byte ordered 16-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in target system byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to read - * the 16-bit little endian byte ordered value from. - * - * @return The 16-bit value at the specified pointer address, if - * necessary, byte reordered. - */ -inline uint16_t Get16(const uint8_t *p) { return nl::IO::LittleEndian::GetUnaligned16(p); } - -/** - * Perform a, potentially unaligned, memory read of the little endian - * byte ordered 32-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in target system byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to read - * the 32-bit little endian byte ordered value from. - * - * @return The 32-bit value at the specified pointer address, if - * necessary, byte reordered. - */ -inline uint32_t Get32(const uint8_t *p) { return nl::IO::LittleEndian::GetUnaligned32(p); } - -/** - * Perform a, potentially unaligned, memory read of the little endian - * byte ordered 64-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in target system byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to read - * the 64-bit little endian byte ordered value from. - * - * @return The 64-bit value at the specified pointer address, if - * necessary, byte reordered. - */ -inline uint64_t Get64(const uint8_t *p) { return nl::IO::LittleEndian::GetUnaligned64(p); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 16-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in little endian byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to write - * the target system byte ordered 16-bit value to in little - * endian byte ordering. - * - * @param[in] v The 16-bit value to write, if necessary, byte reordered. - * - */ -inline void Put16(uint8_t *p, uint16_t v) { nl::IO::LittleEndian::PutUnaligned16(p, v); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 32-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in little endian byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to write - * the target system byte ordered 32-bit value to in little - * endian byte ordering. - * - * @param[in] v The 32-bit value to write, if necessary, byte reordered. - * - */ -inline void Put32(uint8_t *p, uint32_t v) { nl::IO::LittleEndian::PutUnaligned32(p, v); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 64-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in little endian byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to write - * the target system byte ordered 64-bit value to in little - * endian byte ordering. - * - * @param[in] v The 64-bit value to write, if necessary, byte reordered. - * - */ -inline void Put64(uint8_t *p, uint64_t v) { nl::IO::LittleEndian::PutUnaligned64(p, v); } - -/** - * Perform a, potentially unaligned, memory read of the little endian - * byte ordered 16-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 16-bits (2 bytes). - * - * @param[inout] p A reference to a pointer address, potentially - * unaligned, to read the 16-bit little endian byte - * ordered value from and to then increment by 16- - * bits (2 bytes). - * - * @return The 16-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint16_t Read16(uint8_t *& p) { return nl::IO::LittleEndian::ReadUnaligned16((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the little endian - * byte ordered 32-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 32-bits (4 bytes). - * - * @param[inout] p A reference to a pointer address, potentially - * unaligned, to read the 32-bit little endian byte - * ordered value from and to then increment by 32- - * bits (4 bytes). - * - * @return The 32-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint32_t Read32(uint8_t *& p) { return nl::IO::LittleEndian::ReadUnaligned32((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the little endian - * byte ordered 64-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 64-bits (8 bytes). - * - * @param[inout] p A reference to a pointer address, potentially - * unaligned, to read the 64-bit little endian byte - * ordered value from and to then increment by 64- - * bits (8 bytes). - * - * @return The 64-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint64_t Read64(uint8_t *& p) { return nl::IO::LittleEndian::ReadUnaligned64((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the little endian - * byte ordered 16-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 16-bits (2 bytes). - * - * @param[inout] p A reference to a constant pointer address, potentially - * unaligned, to read the 16-bit little endian byte - * ordered value from and to then increment by 16- - * bits (2 bytes). - * - * @return The 16-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint16_t Read16(const uint8_t *& p) { return nl::IO::LittleEndian::ReadUnaligned16((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the little endian - * byte ordered 32-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 32-bits (4 bytes). - * - * @param[inout] p A reference to a constant pointer address, potentially - * unaligned, to read the 32-bit little endian byte - * ordered value from and to then increment by 32- - * bits (4 bytes). - * - * @return The 32-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint32_t Read32(const uint8_t *& p) { return nl::IO::LittleEndian::ReadUnaligned32((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the little endian - * byte ordered 64-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 64-bits (8 bytes). - * - * @param[inout] p A reference to a constant pointer address, potentially - * unaligned, to read the 64-bit little endian byte - * ordered value from and to then increment by 64- - * bits (8 bytes). - * - * @return The 64-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint64_t Read64(const uint8_t *& p) { return nl::IO::LittleEndian::ReadUnaligned64((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 16-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in little endian byte ordering. - * - * @param[in] p A reference to a pointer address, potentially - * unaligned, to write the target system byte - * ordered 16-bit value to in little endian byte - * ordering and to then increment by 16-bits (2 - * bytes). - * - * @param[in] v The 16-bit value to write, if necessary, byte order - * swapped. - * - */ -inline void Write16(uint8_t *& p, uint16_t v) { Put16(p, v); p += sizeof(uint16_t); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 32-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in little endian byte ordering. - * - * @param[in] p A reference to a pointer address, potentially - * unaligned, to write the target system byte - * ordered 32-bit value to in little endian byte - * ordering and to then increment by 32-bits (4 - * bytes). - * - * @param[in] v The 32-bit value to write, if necessary, byte order - * swapped. - * - */ -inline void Write32(uint8_t *& p, uint32_t v) { Put32(p, v); p += sizeof(uint32_t); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 64-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in little endian byte ordering. - * - * @param[in] p A reference to a pointer address, potentially - * unaligned, to write the target system byte - * ordered 64-bit value to in little endian byte - * ordering and to then increment by 64-bits (8 - * bytes). - * - * @param[in] v The 64-bit value to write, if necessary, byte order - * swapped. - * - */ -inline void Write64(uint8_t *& p, uint64_t v) { Put64(p, v); p += sizeof(uint64_t); } - -} // LittleEndian - - -/** - * @namespace chip::Encoding::BigEndian - * - * This namespace provides functions for: - * - *
    - *
  • Performing byte reordering, relative to the host system, by - * value of big endian byte ordered values for 16-, 32-, and - * 64-bit types.
  • - *
  • Safely performing simple, efficient memory-mapped accesses, - * potentially to unaligned memory locations, with or without byte - * reordering, to 8-, 16-, 32-, and 64-bit big endian byte - * ordered quantities, both with and without pointer - * management.
  • - *
- * - * On big endian host systems no actual byte reordering will - * occur. On other systems, byte reordering is peformed as - * appropriate. - * - */ -namespace BigEndian { - -/** - * This conditionally performs, as necessary for the target system, a - * byte order swap by value of the specified 16-bit value, presumed to - * be in big endian byte ordering to the target system (i.e. host) - * byte ordering. - * - * Consequently, on bit endian target systems, this is a no-op and - * on big endian target systems, this performs a reordering. - * - * @param[in] v The 16-bit value to be byte order swapped. - * - * @return The input value, if necessary, byte order swapped. - */ -inline uint16_t HostSwap16(uint16_t v) { return nl::ByteOrder::Swap16BigToHost(v); } - -/** - * This conditionally performs, as necessary for the target system, a - * byte order swap by value of the specified 32-bit value, presumed to - * be in big endian byte ordering to the target system (i.e. host) - * byte ordering. - * - * Consequently, on bit endian target systems, this is a no-op and - * on big endian target systems, this performs a reordering. - * - * @param[in] v The 32-bit value to be byte order swapped. - * - * @return The input value, if necessary, byte order swapped. - */ -inline uint32_t HostSwap32(uint32_t v) { return nl::ByteOrder::Swap32BigToHost(v); } - -/** - * This conditionally performs, as necessary for the target system, a - * byte order swap by value of the specified 64-bit value, presumed to - * be in big endian byte ordering to the target system (i.e. host) - * byte ordering. - * - * Consequently, on bit endian target systems, this is a no-op and - * on big endian target systems, this performs a reordering. - * - * @param[in] v The 64-bit value to be byte order swapped. - * - * @return The input value, if necessary, byte order swapped. - */ -inline uint64_t HostSwap64(uint64_t v) { return nl::ByteOrder::Swap64BigToHost(v); } - -/** - * Perform a, potentially unaligned, memory read of the big endian - * byte ordered 16-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in target system byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to read - * the 16-bit big endian byte ordered value from. - * - * @return The 16-bit value at the specified pointer address, if - * necessary, byte reordered. - */ -inline uint16_t Get16(const uint8_t *p) { return nl::IO::BigEndian::GetUnaligned16(p); } - -/** - * Perform a, potentially unaligned, memory read of the big endian - * byte ordered 32-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in target system byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to read - * the 32-bit big endian byte ordered value from. - * - * @return The 32-bit value at the specified pointer address, if - * necessary, byte reordered. - */ -inline uint32_t Get32(const uint8_t *p) { return nl::IO::BigEndian::GetUnaligned32(p); } - -/** - * Perform a, potentially unaligned, memory read of the big endian - * byte ordered 64-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in target system byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to read - * the 64-bit big endian byte ordered value from. - * - * @return The 64-bit value at the specified pointer address, if - * necessary, byte reordered. - */ -inline uint64_t Get64(const uint8_t *p) { return nl::IO::BigEndian::GetUnaligned64(p); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 16-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in big endian byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to write - * the target system byte ordered 16-bit value to in big - * endian byte ordering. - * - * @param[in] v The 16-bit value to write, if necessary, byte order - * swapped. - * - */ -inline void Put16(uint8_t *p, uint16_t v) { nl::IO::BigEndian::PutUnaligned16(p, v); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 32-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in big endian byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to write - * the target system byte ordered 32-bit value to in big - * endian byte ordering. - * - * @param[in] v The 32-bit value to write, if necessary, byte order - * swapped. - * - */ -inline void Put32(uint8_t *p, uint32_t v) { nl::IO::BigEndian::PutUnaligned32(p, v); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 64-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in big endian byte ordering. - * - * @param[in] p A pointer address, potentially unaligned, to write - * the target system byte ordered 64-bit value to in big - * endian byte ordering. - * - * @param[in] v The 64-bit value to write, if necessary, byte order - * swapped. - * - */ -inline void Put64(uint8_t *p, uint64_t v) { nl::IO::BigEndian::PutUnaligned64(p, v); } - -/** - * Perform a, potentially unaligned, memory read of the big endian - * byte ordered 16-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 16-bits (2 bytes). - * - * @param[inout] p A reference to a pointer address, potentially - * unaligned, to read the 16-bit big endian byte - * ordered value from and to then increment by 16- - * bits (2 bytes). - * - * @return The 16-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint16_t Read16(uint8_t *& p) { return nl::IO::BigEndian::ReadUnaligned16((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the big endian - * byte ordered 32-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 32-bits (4 bytes). - * - * @param[inout] p A reference to a pointer address, potentially - * unaligned, to read the 32-bit big endian byte - * ordered value from and to then increment by 32- - * bits (4 bytes). - * - * @return The 32-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint32_t Read32(uint8_t *& p) { return nl::IO::BigEndian::ReadUnaligned32((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the big endian - * byte ordered 64-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 64-bits (8 bytes). - * - * @param[inout] p A reference to a pointer address, potentially - * unaligned, to read the 64-bit big endian byte - * ordered value from and to then increment by 64- - * bits (8 bytes). - * - * @return The 64-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint64_t Read64(uint8_t *& p) { return nl::IO::BigEndian::ReadUnaligned64((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the big endian - * byte ordered 16-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 16-bits (2 bytes). - * - * @param[inout] p A reference to a constant pointer address, potentially - * unaligned, to read the 16-bit big endian byte - * ordered value from and to then increment by 16- - * bits (2 bytes). - * - * @return The 16-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint16_t Read16(const uint8_t *& p) { return nl::IO::BigEndian::ReadUnaligned16((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the big endian - * byte ordered 32-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 32-bits (4 bytes). - * - * @param[inout] p A reference to a constant pointer address, potentially - * unaligned, to read the 32-bit big endian byte - * ordered value from and to then increment by 32- - * bits (4 bytes). - * - * @return The 32-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint32_t Read32(const uint8_t *& p) { return nl::IO::BigEndian::ReadUnaligned32((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory read of the big endian - * byte ordered 64-bit value from the specified pointer address, - * perform byte reordering, as necessary, for the target system to put - * the value in target system byte ordering, and increment the pointer - * by 64-bits (8 bytes). - * - * @param[inout] p A reference to a constant pointer address, potentially - * unaligned, to read the 64-bit big endian byte - * ordered value from and to then increment by 64- - * bits (8 bytes). - * - * @return The 64-bit value at the specified pointer address, if necessary, - * byte order swapped. - */ -inline uint64_t Read64(const uint8_t *& p) { return nl::IO::BigEndian::ReadUnaligned64((const void *&)p); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 16-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in big endian byte ordering. - * - * @param[in] p A reference to a pointer address, potentially - * unaligned, to write the target system byte - * ordered 16-bit value to in big endian byte - * ordering and to then increment by 16-bits (2 - * bytes). - * - * @param[in] v The 16-bit value to write, if necessary, byte order - * swapped. - * - */ -inline void Write16(uint8_t *& p, uint16_t v) { Put16(p, v); p += sizeof(uint16_t); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 32-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in big endian byte ordering. - * - * @param[in] p A reference to a pointer address, potentially - * unaligned, to write the target system byte - * ordered 32-bit value to in big endian byte - * ordering and to then increment by 32-bits (4 - * bytes). - * - * @param[in] v The 32-bit value to write, if necessary, byte order - * swapped. - * - */ -inline void Write32(uint8_t *& p, uint32_t v) { Put32(p, v); p += sizeof(uint32_t); } - -/** - * Perform a, potentially unaligned, memory write of the target system - * byte ordered 64-bit value to the specified pointer address, - * perform byte reordering, as necessary, for the target system to - * put the value in big endian byte ordering. - * - * @param[in] p A reference to a pointer address, potentially - * unaligned, to write the target system byte - * ordered 64-bit value to in big endian byte - * ordering and to then increment by 64-bits (8 - * bytes). - * - * @param[in] v The 64-bit value to write, if necessary, byte order - * swapped. - * - */ -inline void Write64(uint8_t *& p, uint64_t v) { Put64(p, v); p += sizeof(uint64_t); } - -} // BigEndian - - -} //Encoding -} //chip - -#endif // _CHIPENCODING_H diff --git a/src/system/SystemAlignSize.h b/src/system/SystemAlignSize.h deleted file mode 100644 index 05b6b66c66d71a..00000000000000 --- a/src/system/SystemAlignSize.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * - * - * 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 contains a preprocessor macro that resolves to a - * constant expression that evaluates to the size of an array - * element with alignment padding. - */ - -#ifndef SYSTEMALIGNSIZE_H -#define SYSTEMALIGNSIZE_H - -#define CHIP_SYSTEM_ALIGN_SIZE(ELEMENT, ALIGNMENT) (((ELEMENT) + (ALIGNMENT) - 1) & ~((ALIGNMENT) - 1)) - -#endif // defined(SYSTEMALIGNSIZE_H) diff --git a/src/system/SystemPacketBuffer.h b/src/system/SystemPacketBuffer.h deleted file mode 100644 index 58ad8dbf613581..00000000000000 --- a/src/system/SystemPacketBuffer.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * - * - * - * 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 the chip::System::PacketBuffer class, - * which provides the mechanisms for manipulating packets of * - * octet-serialized data. - */ - -#ifndef SYSTEMPACKETBUFFER_H -#define SYSTEMPACKETBUFFER_H - -// Include configuration header -#include - -// Include dependent headers -#include - -#include "support/DLLUtil.h" - -#include "system/SystemAlignSize.h" -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -namespace chip { -namespace System { - -#if !CHIP_SYSTEM_CONFIG_USE_LWIP -struct pbuf -{ - struct pbuf* next; - void* payload; - uint16_t tot_len; - uint16_t len; - uint16_t ref; -#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0 - uint16_t alloc_size; -#endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0 -}; -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP - -/** @class PacketBuffer - * - * @brief - * The packet buffer class is the core structure used for manipulating packets of octet-serialized data, usually in the - * context of a data communications network, like Bluetooth or the Internet protocol. - * - * In LwIP-based environments, this class is built on top of the pbuf structure defined in that library. In the absence of - * LwIP, chip provides either a malloc-based implementation, or a pool-based implementation that closely approximates the - * memory challenges of deeply embedded devices. - * - * The PacketBuffer class, like many similar structures used in layered network stacks, provide a mechanism to reserve space - * for protocol headers at each layer of a configurable communication stack. For details, see `PacketBuffer::New()` as well - * as LwIP documentation. - * - * PacketBuffer objects are reference-counted, and the prevailing usage mode within chip is "fire-and-forget". As the packet - * (and its underlying PacketBuffer object) is dispatched through various protocol layers, the successful upcall or downcall - * between layers implies ownership transfer, and the callee is responsible for freeing the buffer. On failure of a - * cross-layer call, the responsibilty for freeing the buffer rests with the caller. - * - * New objects of PacketBuffer class are initialized at the beginning of an allocation of memory obtained from the underlying - * environment, e.g. from LwIP pbuf target pools, from the standard C library heap, from an internal buffer pool. In the - * simple case, the size of the data buffer is #CHIP_SYSTEM_PACKETBUFFER_SIZE. A composer is provided that permits usage of - * data buffers of other sizes. - * - * PacketBuffer objects may be chained to accomodate larger payloads. Chaining, however, is not transparent, and users of the - * class must explicitly decide to support chaining. Examples of classes written with chaining support are as follows: - * - * @ref chip::chipTLVReader - * @ref chip::chipTLVWriter - * - */ -class DLL_EXPORT PacketBuffer : private pbuf -{ -public: - size_t AllocSize(void) const; - - uint8_t* Start(void) const; - void SetStart(uint8_t* aNewStart); - - uint16_t DataLength(void) const; - void SetDataLength(uint16_t aNewLen, PacketBuffer* aChainHead = NULL); - - uint16_t TotalLength(void) const; - - uint16_t MaxDataLength(void) const; - uint16_t AvailableDataLength(void) const; - - uint16_t ReservedSize(void) const; - - PacketBuffer* Next(void) const; - - void AddToEnd(PacketBuffer* aPacket); - PacketBuffer* DetachTail(void); - void CompactHead(void); - PacketBuffer* Consume(uint16_t aConsumeLength); - void ConsumeHead(uint16_t aConsumeLength); - bool EnsureReservedSize(uint16_t aReservedSize); - bool AlignPayload(uint16_t aAlignBytes); - - void AddRef(void); - - static PacketBuffer* NewWithAvailableSize(size_t aAvailableSize); - static PacketBuffer* NewWithAvailableSize(uint16_t aReservedSize, size_t aAvailableSize); - - static PacketBuffer* New(void); - static PacketBuffer* New(uint16_t aReservedSize); - - static PacketBuffer* RightSize(PacketBuffer *aPacket); - - static void Free(PacketBuffer* aPacket); - static PacketBuffer* FreeHead(PacketBuffer* aPacket); - -private: -#if !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC - static PacketBuffer* sFreeList; - - static PacketBuffer* BuildFreeList(void); -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC - - void Clear(void); -}; - -} // namespace System -} // namespace chip - -// Sizing definitions - -/** - * @def CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE - * - * The effective size of the packet buffer structure. - * - * TODO: This is an implementation details that does not need to be public and should be moved to the source file. - */ - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#define CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE LWIP_MEM_ALIGN_SIZE(sizeof(struct ::pbuf)) -#else // CHIP_SYSTEM_CONFIG_USE_LWIP -#define CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE CHIP_SYSTEM_ALIGN_SIZE(sizeof(::chip::System::PacketBuffer), 4) -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - - -/** - * @def CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX - * - * See SystemConfig.h for full description. This is defined in here specifically for LwIP platform to preserve backwards - * compatibility. - * - * TODO: This is an implementation details that does not need to be public and should be moved to the source file. - * - */ -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX (LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE) -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -/** - * @def CHIP_SYSTEM_PACKETBUFFER_SIZE - * - * The memory footprint of a PacketBuffer object, computed from max capacity size and the size of the packet buffer structure. - * - * TODO: This is an implementation details that does not need to be public and should be moved to the source file. - */ - -#define CHIP_SYSTEM_PACKETBUFFER_SIZE (CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE) - -namespace chip { -namespace System { - -// -// Pool allocation for PacketBuffer objects (toll-free bridged with LwIP pbuf allocator if CHIP_SYSTEM_CONFIG_USE_LWIP) -// -#if !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC - -typedef union -{ - PacketBuffer Header; - uint8_t Block[CHIP_SYSTEM_PACKETBUFFER_SIZE]; -} BufferPoolElement; - -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC - -/** - * Return the size of the allocation including the reserved and payload data spaces but not including space - * allocated for the PacketBuffer structure. - * - * @note The allocation size is equal or greater than \c aAllocSize paramater to \c Create method). - * - * @return size of the allocation - */ -inline size_t PacketBuffer::AllocSize(void) const -{ -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if LWIP_PBUF_FROM_CUSTOM_POOLS - // Temporary workaround for custom pbufs by assuming size to be PBUF_POOL_BUFSIZE - if (this->flags & PBUF_FLAG_IS_CUSTOM) - return LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE; - else - return LWIP_MEM_ALIGN_SIZE(memp_sizes[this->pool]) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE; -#else // !LWIP_PBUF_FROM_CUSTOM_POOLS - return LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE; -#endif // !LWIP_PBUF_FROM_CUSTOM_POOLS -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0 - return static_cast(this->alloc_size); -#else // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC != 0 - extern BufferPoolElement gDummyBufferPoolElement; - return sizeof(gDummyBufferPoolElement.Block) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE; -#endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC != 0 -#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP -} - -} // namespace System -} // namespace chip - -#endif // defined(SYSTEMPACKETBUFFER_H)