diff --git a/examples/lighting-app/efr32/args.gni b/examples/lighting-app/efr32/args.gni index 1b73ad66dcea58..0f2b60d59f6054 100644 --- a/examples/lighting-app/efr32/args.gni +++ b/examples/lighting-app/efr32/args.gni @@ -22,3 +22,4 @@ pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip" pw_assert_BACKEND = "$dir_pw_assert_log" chip_enable_openthread = true chip_openthread_ftd = true +chip_system_config_use_open_thread_udp = true diff --git a/examples/platform/efr32/project_include/OpenThreadConfig.h b/examples/platform/efr32/project_include/OpenThreadConfig.h index eea8f866a14f8a..1e8721c6d24401 100644 --- a/examples/platform/efr32/project_include/OpenThreadConfig.h +++ b/examples/platform/efr32/project_include/OpenThreadConfig.h @@ -61,6 +61,9 @@ #define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 0 #define OPENTHREAD_CONFIG_TCP_ENABLE 0 +// Support udp multicast by enabling Multicast Listener Registration (MLR) +#define OPENTHREAD_CONFIG_MLR_ENABLE 1 + // Use the SiLabs-supplied default platform configuration for remainder // of OpenThread config options. // diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 1364d11ecd956c..a4a39cbc246a01 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -133,6 +133,9 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint err = mTransports.Init(UdpListenParameters(DeviceLayer::UDPEndPointManager()) .SetAddressType(IPAddressType::kIPv6) .SetListenPort(mSecuredServicePort) +#if CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_UDP + .SetNativeParams(chip::DeviceLayer::ThreadStackMgrImpl().OTInstance()) +#endif // CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_UDP #if INET_CONFIG_ENABLE_IPV4 , @@ -151,10 +154,10 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint #endif SuccessOrExit(err); - // Enable Group Listening - // TODO : Fix this once GroupDataProvider is implemented #Issue 11075 - // for (iterate through all GroupDataProvider multicast Address) - // { +// Enable Group Listening +// TODO : Fix this once GroupDataProvider is implemented #Issue 11075 +// for (iterate through all GroupDataProvider multicast Address) +// { #ifdef CHIP_ENABLE_GROUP_MESSAGING_TESTS err = mTransports.MulticastGroupJoinLeave(Transport::PeerAddress::Multicast(1, 1234), true); SuccessOrExit(err); diff --git a/src/inet/BUILD.gn b/src/inet/BUILD.gn index fc94850e7e7f8d..164c0076c5a546 100644 --- a/src/inet/BUILD.gn +++ b/src/inet/BUILD.gn @@ -24,6 +24,10 @@ import("${chip_root}/src/lwip/lwip.gni") import("${chip_root}/src/platform/device.gni") import("inet.gni") +if (chip_system_config_use_open_thread_udp) { + import("//build_overrides/openthread.gni") +} + declare_args() { # Extra header to include in SystemConfig.h for project. chip_inet_project_config_include = "" @@ -50,10 +54,14 @@ buildconfig_header("inet_buildconfig") { [ "INET_PLATFORM_CONFIG_INCLUDE=${chip_inet_platform_config_include}" ] } - defines += [ - "INET_TCP_END_POINT_IMPL_CONFIG_FILE=", - "INET_UDP_END_POINT_IMPL_CONFIG_FILE=", - ] + defines += [ "INET_TCP_END_POINT_IMPL_CONFIG_FILE=" ] + if (chip_system_config_use_open_thread_udp) { + defines += [ + "INET_UDP_END_POINT_IMPL_CONFIG_FILE=", + ] + } else { + defines += [ "INET_UDP_END_POINT_IMPL_CONFIG_FILE=" ] + } } source_set("inet_config_header") { @@ -105,6 +113,16 @@ static_library("inet") { public_deps += [ "${chip_root}/src/lwip" ] } + if (chip_system_config_use_open_thread_udp) { + if (chip_openthread_ftd) { + public_deps += + [ "${chip_root}/third_party/openthread/repo:libopenthread-ftd" ] + } else { + public_deps += + [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ] + } + } + if (chip_inet_config_enable_tcp_endpoint) { sources += [ "TCPEndPoint.cpp", @@ -119,10 +137,20 @@ static_library("inet") { sources += [ "UDPEndPoint.cpp", "UDPEndPoint.h", - "UDPEndPointImpl${chip_system_config_inet}.cpp", - "UDPEndPointImpl${chip_system_config_inet}.h", "UDPEndPointImpl.h", ] + + if (chip_system_config_use_open_thread_udp) { + sources += [ + "UDPEndPointImpl_OpenThread.cpp", + "UDPEndPointImpl_OpenThread.h", + ] + } else { + sources += [ + "UDPEndPointImpl${chip_system_config_inet}.cpp", + "UDPEndPointImpl${chip_system_config_inet}.h", + ] + } } if (chip_with_nlfaultinjection) { diff --git a/src/inet/UDPEndPoint.h b/src/inet/UDPEndPoint.h index 005dccf26eb8b5..9cea83fb3cbc88 100644 --- a/src/inet/UDPEndPoint.h +++ b/src/inet/UDPEndPoint.h @@ -37,6 +37,8 @@ #include #include +struct otInstance; + namespace chip { namespace Inet { @@ -245,6 +247,13 @@ class DLL_EXPORT UDPEndPoint : public EndPointBasis */ virtual void Free() = 0; + /** + * Set Network Native Parameters (optional) + * + * Some networking stack requires additionnal parameters + */ + virtual inline void SetNativeParams(void * params) { (void) params; } + protected: UDPEndPoint(EndPointManager & endPointManager) : EndPointBasis(endPointManager), mState(State::kReady), OnMessageReceived(nullptr), OnReceiveError(nullptr) diff --git a/src/inet/UDPEndPointImpl_OpenThread.cpp b/src/inet/UDPEndPointImpl_OpenThread.cpp new file mode 100644 index 00000000000000..7822c33f83aad2 --- /dev/null +++ b/src/inet/UDPEndPointImpl_OpenThread.cpp @@ -0,0 +1,265 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2018 Google LLC. + * Copyright (c) 2013-2018 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include + +#include + +namespace chip { +namespace Inet { + +void UDPEndPointImplOT::handleUdpReceive(void * aContext, otMessage * aMessage, const otMessageInfo * aMessageInfo) +{ + UDPEndPointImplOT * ep = static_cast(aContext); + IPPacketInfo pktInfo; + uint16_t msgLen = otMessageGetLength(aMessage); + System::PacketBufferHandle payload; +#if CHIP_DETAIL_LOGGING + static uint16_t msgReceivedCount = 0; + char sourceStr[Inet::IPAddress::kMaxStringLength]; + char destStr[Inet::IPAddress::kMaxStringLength]; +#endif + + if (msgLen > System::PacketBuffer::kMaxSizeWithoutReserve) + { + ChipLogError(Inet, "UDP message too long, discarding. Size received %d", msgLen); + return; + } + + pktInfo.SrcAddress = chip::DeviceLayer::Internal::ToIPAddress(aMessageInfo->mPeerAddr); + pktInfo.DestAddress = chip::DeviceLayer::Internal::ToIPAddress(aMessageInfo->mSockAddr); + pktInfo.SrcPort = aMessageInfo->mPeerPort; + pktInfo.DestPort = aMessageInfo->mSockPort; + + payload = System::PacketBufferHandle::New(msgLen, 0); + + if (payload.IsNull()) + { + ChipLogError(Inet, "Failed to allocate a System buffer of size %d for UDP Message reception.", msgLen); + return; + } + +#if CHIP_DETAIL_LOGGING + pktInfo.SrcAddress.ToString(sourceStr, Inet::IPAddress::kMaxStringLength); + pktInfo.DestAddress.ToString(destStr, Inet::IPAddress::kMaxStringLength); + + ChipLogDetail(Inet, + "UDP Message Received packet nb : %d with the following data :\r\nSrcAddr : %s\r\nSrc Port : %d\r\n\r\nDestAddr " + ": %s\r\nDest Port %d\r\nPayload Length %d", + ++msgReceivedCount, sourceStr, pktInfo.SrcPort, destStr, pktInfo.DestPort, msgLen); + +#endif + + memcpy(payload->Start(), &pktInfo, sizeof(IPPacketInfo)); + + if (otMessageRead(aMessage, 0, payload->Start() + sizeof(IPPacketInfo), msgLen) != msgLen) + { + ChipLogError(Inet, "Failed to copy OpenThread buffer into System Packet buffer"); + return; + } + payload->SetDataLength(msgLen + sizeof(IPPacketInfo)); + + ep->Retain(); + CHIP_ERROR err = ep->GetSystemLayer().ScheduleLambda([ep, p = System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(payload)] { + ep->HandleDataReceived(System::PacketBufferHandle::Adopt(p)); + ep->Release(); + }); + if (err == CHIP_NO_ERROR) + { + // If ScheduleLambda() succeeded, it has ownership of the buffer, so we need to release it (without freeing it). + static_cast(std::move(payload).UnsafeRelease()); + } + else + { + ep->Release(); + } +} + +CHIP_ERROR UDPEndPointImplOT::IPv6Bind(otUdpSocket & socket, const IPAddress & address, uint16_t port, InterfaceId interface) +{ + (void) interface; + otError err = OT_ERROR_NONE; + otSockAddr listenSockAddr; + + memset(&socket, 0, sizeof(socket)); + memset(&listenSockAddr, 0, sizeof(listenSockAddr)); + + listenSockAddr.mPort = port; + listenSockAddr.mAddress = chip::DeviceLayer::Internal::ToOpenThreadIP6Address(address); + + otUdpOpen(mOTInstance, &socket, handleUdpReceive, this); + otUdpBind(mOTInstance, &socket, &listenSockAddr, OT_NETIF_THREAD); + + return chip::DeviceLayer::Internal::MapOpenThreadError(err); +} + +CHIP_ERROR UDPEndPointImplOT::BindImpl(IPAddressType addressType, const IPAddress & addr, uint16_t port, InterfaceId interface) +{ + + if (addressType != IPAddressType::kIPv6) + { + return INET_ERROR_WRONG_ADDRESS_TYPE; + } + + ReturnErrorOnFailure(IPv6Bind(mSocket, addr, port, interface)); + mBoundPort = port; + mBoundIntfId = interface; + + return CHIP_NO_ERROR; +} + +InterfaceId UDPEndPointImplOT::GetBoundInterface() const +{ + return mBoundIntfId; +} + +uint16_t UDPEndPointImplOT::GetBoundPort() const +{ + return mBoundPort; +} + +CHIP_ERROR UDPEndPointImplOT::ListenImpl() +{ + // Nothing to do. Callback was set upon Binding call. + return CHIP_NO_ERROR; +} + +void UDPEndPointImplOT::HandleDataReceived(System::PacketBufferHandle && msg) +{ + if ((mState == State::kListening) && (OnMessageReceived != nullptr)) + { + const IPPacketInfo * pktInfo = GetPacketInfo(msg); + + if (pktInfo != nullptr) + { + const IPPacketInfo pktInfoCopy = *pktInfo; // copy the address info so that the app can free the + // PacketBuffer without affecting access to address info. + + msg->ConsumeHead(sizeof(IPPacketInfo)); + OnMessageReceived(this, std::move(msg), &pktInfoCopy); + } + else + { + if (OnReceiveError != nullptr) + { + OnReceiveError(this, CHIP_ERROR_INBOUND_MESSAGE_TOO_BIG, nullptr); + } + } + } +} + +CHIP_ERROR UDPEndPointImplOT::SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) +{ + (void) aIPVersion; + (void) aLoopback; + // TODO + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR UDPEndPointImplOT::BindInterfaceImpl(IPAddressType addressType, InterfaceId interfaceId) +{ + (void) addressType; + (void) interfaceId; + return CHIP_NO_ERROR; +} + +CHIP_ERROR UDPEndPointImplOT::SendMsgImpl(const IPPacketInfo * aPktInfo, System::PacketBufferHandle && msg) +{ + otError error = OT_ERROR_NONE; + otMessage * message; + otMessageInfo messageInfo; + + // For now the entire message must fit within a single buffer. + VerifyOrReturnError(!msg->HasChainedBuffer(), CHIP_ERROR_MESSAGE_TOO_LONG); + + memset(&messageInfo, 0, sizeof(messageInfo)); + + messageInfo.mSockAddr = chip::DeviceLayer::Internal::ToOpenThreadIP6Address(aPktInfo->SrcAddress); + messageInfo.mPeerAddr = chip::DeviceLayer::Internal::ToOpenThreadIP6Address(aPktInfo->DestAddress); + messageInfo.mPeerPort = aPktInfo->DestPort; + + message = otUdpNewMessage(mOTInstance, NULL); + VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS); + + error = otMessageAppend(message, msg->Start(), msg->DataLength()); + + if (error == OT_ERROR_NONE) + { + error = otUdpSend(mOTInstance, &mSocket, message, &messageInfo); + } + +exit: + if (error != OT_ERROR_NONE && message != NULL) + { + otMessageFree(message); + } + + return chip::DeviceLayer::Internal::MapOpenThreadError(error); +} + +void UDPEndPointImplOT::CloseImpl() +{ + if (otUdpIsOpen(mOTInstance, &mSocket)) + { + otUdpClose(mOTInstance, &mSocket); + } +} + +void UDPEndPointImplOT::Free() +{ + Close(); + Release(); +} + +CHIP_ERROR UDPEndPointImplOT::IPv6JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join) +{ + const otIp6Address otAddress = chip::DeviceLayer::Internal::ToOpenThreadIP6Address(aAddress); + + if (join) + { + return chip::DeviceLayer::Internal::MapOpenThreadError(otIp6SubscribeMulticastAddress(mOTInstance, &otAddress)); + } + else + { + return chip::DeviceLayer::Internal::MapOpenThreadError(otIp6UnsubscribeMulticastAddress(mOTInstance, &otAddress)); + } +} + +IPPacketInfo * UDPEndPointImplOT::GetPacketInfo(const System::PacketBufferHandle & aBuffer) +{ + if (!aBuffer->EnsureReservedSize(sizeof(IPPacketInfo))) + { + return nullptr; + } + + uintptr_t lStart = (uintptr_t) aBuffer->Start(); + uintptr_t lPacketInfoStart = lStart - sizeof(IPPacketInfo); + + // Align to a 4-byte boundary + return reinterpret_cast(lPacketInfoStart & ~(sizeof(uint32_t) - 1)); +} + +} // namespace Inet +} // namespace chip diff --git a/src/inet/UDPEndPointImpl_OpenThread.h b/src/inet/UDPEndPointImpl_OpenThread.h new file mode 100644 index 00000000000000..e6299c40c95ea8 --- /dev/null +++ b/src/inet/UDPEndPointImpl_OpenThread.h @@ -0,0 +1,71 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2018 Google LLC + * Copyright (c) 2013-2017 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace Inet { + +class UDPEndPointImplOT : public UDPEndPoint +{ +public: + UDPEndPointImplOT(EndPointManager & endPointManager) : + UDPEndPoint(endPointManager), mBoundIntfId(InterfaceId::Null()) + {} + + // UDPEndPoint overrides. + InterfaceId GetBoundInterface() const override; + uint16_t GetBoundPort() const override; + void Free() override; + void HandleDataReceived(System::PacketBufferHandle && msg); + inline void SetNativeParams(void * params) { mOTInstance = static_cast(params); } + CHIP_ERROR SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) override; + CHIP_ERROR BindInterfaceImpl(IPAddressType addressType, InterfaceId interfaceId) override; + +private: + // UDPEndPoint overrides. + CHIP_ERROR IPv6JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join) override; + CHIP_ERROR BindImpl(IPAddressType addressType, const IPAddress & address, uint16_t port, InterfaceId interfaceId) override; + CHIP_ERROR ListenImpl() override; + CHIP_ERROR SendMsgImpl(const IPPacketInfo * pktInfo, chip::System::PacketBufferHandle && msg) override; + void CloseImpl() override; + CHIP_ERROR IPv6Bind(otUdpSocket & socket, const IPAddress & address, uint16_t port, InterfaceId interface); + static IPPacketInfo * GetPacketInfo(const System::PacketBufferHandle & aBuffer); + + static void handleUdpReceive(void * aContext, otMessage * aMessage, const otMessageInfo * aMessageInfo); + + InterfaceId mBoundIntfId; + uint16_t mBoundPort; + otUdpSocket mSocket; + otInstance * mOTInstance = nullptr; +}; + +using UDPEndPointImpl = UDPEndPointImplOT; + +} // namespace Inet +} // namespace chip diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread_LwIP.cpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread_LwIP.cpp index 957dc20a05ab24..171751d58947e7 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread_LwIP.cpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread_LwIP.cpp @@ -34,8 +34,13 @@ #include #include +#include + #include +#include +#include + namespace chip { namespace DeviceLayer { namespace Internal { @@ -225,6 +230,39 @@ void GenericThreadStackManagerImpl_OpenThread_LwIP::UpdateThreadInter addrAssigned[addrIdx] = true; } } + +// Multicast won't work with LWIP on top of OT +// Duplication of listeners, unecessary timers, buffer duplication, hardfault etc... +#if CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_UDP + // Refresh Multicast listening + if (GenericThreadStackManagerImpl_OpenThread::IsThreadAttachedNoLock()) + { + ChipLogDetail(DeviceLayer, "Thread Attached updating Multicast address"); + + Credentials::GroupDataProvider * provider = Credentials::GetGroupDataProvider(); + TransportMgrBase * transportMgr = &(chip::Server::GetInstance().GetTransportManager()); + Credentials::GroupDataProvider::GroupInfo group; + CHIP_ERROR err = CHIP_NO_ERROR; + for (const FabricInfo & fabricInfo : Server::GetInstance().GetFabricTable()) + { + auto it = provider->IterateGroupInfo(fabricInfo.GetFabricIndex()); + if (it) + { + while (it->Next(group)) + { + err = transportMgr->MulticastGroupJoinLeave( + Transport::PeerAddress::Multicast(fabricInfo.GetFabricIndex(), group.group_id), true); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Failed to Join Multicast Group: %s", err.AsString()); + break; + } + } + it->Release(); + } + } + } +#endif // CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_UDP } ChipLogDetail(DeviceLayer, "LwIP Thread interface addresses %s", isInterfaceUp ? "updated" : "cleared"); diff --git a/src/system/BUILD.gn b/src/system/BUILD.gn index 874bc3cdc0171d..8a60c03dbb9b56 100644 --- a/src/system/BUILD.gn +++ b/src/system/BUILD.gn @@ -59,6 +59,7 @@ buildconfig_header("system_buildconfig") { "CHIP_WITH_NLFAULTINJECTION=${chip_with_nlfaultinjection}", "CHIP_SYSTEM_CONFIG_USE_DISPATCH=${chip_system_config_use_dispatch}", "CHIP_SYSTEM_CONFIG_USE_LWIP=${chip_system_config_use_lwip}", + "CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_UDP=${chip_system_config_use_open_thread_udp}", "CHIP_SYSTEM_CONFIG_USE_SOCKETS=${chip_system_config_use_sockets}", "CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK=false", "CHIP_SYSTEM_CONFIG_POSIX_LOCKING=${chip_system_config_posix_locking}", diff --git a/src/system/SystemPacketBuffer.h b/src/system/SystemPacketBuffer.h index 031a397c422bba..4f877afb0bf048 100644 --- a/src/system/SystemPacketBuffer.h +++ b/src/system/SystemPacketBuffer.h @@ -847,6 +847,15 @@ namespace Inet { class UDPEndPointImplLwIP; } // namespace Inet +#if CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_UDP +// TODO : Temp Implementation issue : 13085 +// Still use LwIP buffer even if using OpenThread UDP implementation +// since decoupling of LwIP from OpenThread is still in progress +namespace Inet { +class UDPEndPointImplOT; +} // namespace Inet +#endif + namespace System { /** @@ -864,6 +873,12 @@ class LwIPPacketBufferView : public PacketBufferHandle */ static struct pbuf * UnsafeGetLwIPpbuf(const PacketBufferHandle & handle) { return PacketBufferHandle::GetLwIPpbuf(handle); } friend class Inet::UDPEndPointImplLwIP; +#if CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_UDP + // TODO : Temp Implementation issue : 13085 + // Still use LwIP buffer even if using OpenThread UDP implementation + // since decoupling of LwIP from OpenThread is still in progress + friend class Inet::UDPEndPointImplOT; +#endif }; } // namespace System diff --git a/src/system/system.gni b/src/system/system.gni index 12e371a7c29d1b..71fb601192f99d 100644 --- a/src/system/system.gni +++ b/src/system/system.gni @@ -31,6 +31,9 @@ declare_args() { # Enable metrics collection. chip_system_config_provide_statistics = true + + # Use OpenThread UDP stack directly + chip_system_config_use_open_thread_udp = false } declare_args() { diff --git a/src/transport/raw/UDP.cpp b/src/transport/raw/UDP.cpp index d1d996fa6a2043..c27190ad7b1e6f 100644 --- a/src/transport/raw/UDP.cpp +++ b/src/transport/raw/UDP.cpp @@ -49,12 +49,14 @@ CHIP_ERROR UDP::Init(UdpListenParameters & params) err = params.GetEndPointManager()->NewEndPoint(&mUDPEndPoint); SuccessOrExit(err); + mUDPEndPoint->SetNativeParams(params.GetNativeParams()); + ChipLogDetail(Inet, "UDP::Init bind&listen port=%d", params.GetListenPort()); err = mUDPEndPoint->Bind(params.GetAddressType(), Inet::IPAddress::Any, params.GetListenPort(), params.GetInterfaceId()); SuccessOrExit(err); - err = mUDPEndPoint->Listen(OnUdpReceive, nullptr /*onReceiveError*/, this); + err = mUDPEndPoint->Listen(OnUdpReceive, OnUdpError, this); SuccessOrExit(err); mUDPEndpointType = params.GetAddressType(); @@ -125,6 +127,11 @@ void UDP::OnUdpReceive(Inet::UDPEndPoint * endPoint, System::PacketBufferHandle } } +void UDP::OnUdpError(Inet::UDPEndPoint * endPoint, CHIP_ERROR err, const Inet::IPPacketInfo * pktInfo) +{ + ChipLogError(Inet, "Failed to receive UDP message: %s", ErrorStr(err)); +} + CHIP_ERROR UDP::MulticastGroupJoinLeave(const Transport::PeerAddress & address, bool join) { char addressStr[Transport::PeerAddress::kMaxToStringSize]; diff --git a/src/transport/raw/UDP.h b/src/transport/raw/UDP.h index fcdc624eb06d81..25fb5f3ed71839 100644 --- a/src/transport/raw/UDP.h +++ b/src/transport/raw/UDP.h @@ -34,6 +34,10 @@ #include #include +#if CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_UDP +struct otInstance; +#endif // CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_UDP + namespace chip { namespace Transport { @@ -71,11 +75,23 @@ class UdpListenParameters return *this; } + /** + * Networking Stack Native parameter (optional) + */ + void * GetNativeParams() const { return mNativeParams; } + UdpListenParameters & SetNativeParams(void * params) + { + mNativeParams = params; + + return *this; + } + private: Inet::EndPointManager * mEndPointManager; ///< Associated endpoint factory Inet::IPAddressType mAddressType = Inet::IPAddressType::kIPv6; ///< type of listening socket uint16_t mListenPort = CHIP_PORT; ///< UDP listen port Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null(); ///< Interface to listen on + void * mNativeParams = nullptr; }; /** Implements a transport using UDP. */ @@ -133,6 +149,8 @@ class DLL_EXPORT UDP : public Base static void OnUdpReceive(Inet::UDPEndPoint * endPoint, System::PacketBufferHandle && buffer, const Inet::IPPacketInfo * pktInfo); + static void OnUdpError(Inet::UDPEndPoint * endPoint, CHIP_ERROR err, const Inet::IPPacketInfo * pktInfo); + Inet::UDPEndPoint * mUDPEndPoint = nullptr; ///< UDP socket used by the transport Inet::IPAddressType mUDPEndpointType = Inet::IPAddressType::kUnknown; ///< Socket listening type State mState = State::kNotReady; ///< State of the UDP transport