diff --git a/examples/minimal-mdns/client.cpp b/examples/minimal-mdns/client.cpp index f525d9b2c8c128..4706383b19061a 100644 --- a/examples/minimal-mdns/client.cpp +++ b/examples/minimal-mdns/client.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include "AllInterfaceListener.h" #include "PacketReporter.h" diff --git a/examples/minimal-mdns/server.cpp b/examples/minimal-mdns/server.cpp index d4456001c16875..1695930c9fa486 100644 --- a/examples/minimal-mdns/server.cpp +++ b/examples/minimal-mdns/server.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include "AllInterfaceListener.h" #include "PacketReporter.h" diff --git a/examples/platform/nrfconnect/util/test/TestInetCommon.cpp b/examples/platform/nrfconnect/util/test/TestInetCommon.cpp index 7ead6832f3badc..192f14477daebe 100644 --- a/examples/platform/nrfconnect/util/test/TestInetCommon.cpp +++ b/examples/platform/nrfconnect/util/test/TestInetCommon.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #if CHIP_SYSTEM_CONFIG_USE_SOCKETS #include @@ -114,7 +113,7 @@ void ServiceEvents(struct ::timeval & aSleepTime) FD_ZERO(&exceptFDs); #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - if (gSystemLayer.State() == System::kLayerState_Initialized) + if (gSystemLayer.State() == System::LayerState::kInitialized) gSystemLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS @@ -131,7 +130,7 @@ void ServiceEvents(struct ::timeval & aSleepTime) } #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS - if (gSystemLayer.State() == System::kLayerState_Initialized) + if (gSystemLayer.State() == System::LayerState::kInitialized) { #if CHIP_SYSTEM_CONFIG_USE_SOCKETS diff --git a/src/app/EventManagement.cpp b/src/app/EventManagement.cpp index efb7fba4b8f94d..769a17b5b873ce 100644 --- a/src/app/EventManagement.cpp +++ b/src/app/EventManagement.cpp @@ -24,7 +24,6 @@ #include #include #include -#include using namespace chip::TLV; diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp index 5f75e7e6559488..b6d15a2932d3a0 100644 --- a/src/app/tests/TestReadInteraction.cpp +++ b/src/app/tests/TestReadInteraction.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/src/app/tests/integration/MockEvents.cpp b/src/app/tests/integration/MockEvents.cpp index 30270bef152047..6386e772dde48c 100644 --- a/src/app/tests/integration/MockEvents.cpp +++ b/src/app/tests/integration/MockEvents.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include static uint64_t kLivenessDeviceStatus = chip::TLV::ContextTag(1); diff --git a/src/app/util/af-event.cpp b/src/app/util/af-event.cpp index 04c31acb508263..24e9ff866184ed 100644 --- a/src/app/util/af-event.cpp +++ b/src/app/util/af-event.cpp @@ -43,7 +43,6 @@ #include #include -#include #define EMBER_MAX_EVENT_CONTROL_DELAY_MS (UINT32_MAX / 2) #define EMBER_MAX_EVENT_CONTROL_DELAY_QS (EMBER_MAX_EVENT_CONTROL_DELAY_MS >> 8) diff --git a/src/inet/EndPointBasis.cpp b/src/inet/EndPointBasis.cpp index 9cae140506d0a7..6d4ca2c6d2b6e0 100644 --- a/src/inet/EndPointBasis.cpp +++ b/src/inet/EndPointBasis.cpp @@ -39,7 +39,7 @@ void EndPointBasis::InitEndPointBasis(InetLayer & aInetLayer, void * aAppState) #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - (void) mSocket.Init(aInetLayer.SystemLayer()->WatchableEventsManager()); + mSocket = INET_INVALID_SOCKET_FD; #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS } diff --git a/src/inet/EndPointBasis.h b/src/inet/EndPointBasis.h index 2d7411351e7c42..8f61b87a73edbd 100644 --- a/src/inet/EndPointBasis.h +++ b/src/inet/EndPointBasis.h @@ -35,7 +35,7 @@ #include #if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include +#include #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS #if CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK @@ -97,9 +97,10 @@ class DLL_EXPORT EndPointBasis : public InetLayerBasis #endif #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - System::WatchableSocket mSocket; /**< Encapsulated socket descriptor. */ - IPAddressType mAddrType; /**< Protocol family, i.e. IPv4 or IPv6. */ -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS + int mSocket; /**< Encapsulated socket descriptor. */ + IPAddressType mAddrType; /**< Protocol family, i.e. IPv4 or IPv6. */ + System::SocketWatchToken mWatch; /**< Socket event watcher */ +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS #if CHIP_SYSTEM_CONFIG_USE_LWIP /** Encapsulated LwIP protocol control block */ @@ -145,7 +146,7 @@ inline bool EndPointBasis::IsNetworkFrameworkEndPoint(void) const #if CHIP_SYSTEM_CONFIG_USE_SOCKETS inline bool EndPointBasis::IsSocketsEndPoint() const { - return mSocket.HasFD(); + return mSocket != INET_INVALID_SOCKET_FD; } #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS diff --git a/src/inet/IPEndPointBasis.cpp b/src/inet/IPEndPointBasis.cpp index f34ada46a08775..4ae9da8e6b4215 100644 --- a/src/inet/IPEndPointBasis.cpp +++ b/src/inet/IPEndPointBasis.cpp @@ -389,7 +389,7 @@ CHIP_ERROR IPEndPointBasis::SetMulticastLoopback(IPVersion aIPVersion, bool aLoo #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsSetMulticastLoopback(mSocket.GetFD(), aIPVersion, aLoopback); + lRetval = SocketsSetMulticastLoopback(mSocket, aIPVersion, aLoopback); SuccessOrExit(lRetval); exit: @@ -449,7 +449,7 @@ CHIP_ERROR IPEndPointBasis::JoinMulticastGroup(InterfaceId aInterfaceId, const I #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsIPv4JoinLeaveMulticastGroup(mSocket.GetFD(), aInterfaceId, aAddress, IP_ADD_MEMBERSHIP); + lRetval = SocketsIPv4JoinLeaveMulticastGroup(mSocket, aInterfaceId, aAddress, IP_ADD_MEMBERSHIP); SuccessOrExit(lRetval); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS } @@ -474,7 +474,7 @@ CHIP_ERROR IPEndPointBasis::JoinMulticastGroup(InterfaceId aInterfaceId, const I #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsIPv6JoinMulticastGroup(mSocket.GetFD(), aInterfaceId, aAddress); + lRetval = SocketsIPv6JoinMulticastGroup(mSocket, aInterfaceId, aAddress); SuccessOrExit(lRetval); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS } @@ -541,7 +541,7 @@ CHIP_ERROR IPEndPointBasis::LeaveMulticastGroup(InterfaceId aInterfaceId, const #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsIPv4JoinLeaveMulticastGroup(mSocket.GetFD(), aInterfaceId, aAddress, IP_DROP_MEMBERSHIP); + lRetval = SocketsIPv4JoinLeaveMulticastGroup(mSocket, aInterfaceId, aAddress, IP_DROP_MEMBERSHIP); SuccessOrExit(lRetval); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS } @@ -566,7 +566,7 @@ CHIP_ERROR IPEndPointBasis::LeaveMulticastGroup(InterfaceId aInterfaceId, const #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - lRetval = SocketsIPv6LeaveMulticastGroup(mSocket.GetFD(), aInterfaceId, aAddress); + lRetval = SocketsIPv6LeaveMulticastGroup(mSocket, aInterfaceId, aAddress); SuccessOrExit(lRetval); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS } @@ -693,21 +693,21 @@ CHIP_ERROR IPEndPointBasis::Bind(IPAddressType aAddressType, const IPAddress & a } sa.sin6_scope_id = static_cast(aInterfaceId); - if (bind(mSocket.GetFD(), reinterpret_cast(&sa), static_cast(sizeof(sa))) != 0) + if (bind(mSocket, reinterpret_cast(&sa), static_cast(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 == CHIP_NO_ERROR) - setsockopt(mSocket.GetFD(), IPPROTO_IPV6, IPV6_MULTICAST_IF, &aInterfaceId, sizeof(aInterfaceId)); + 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.GetFD(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)); + setsockopt(mSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)); #endif // defined(IPV6_MULTICAST_HOPS) } #if INET_CONFIG_ENABLE_IPV4 @@ -722,26 +722,26 @@ CHIP_ERROR IPEndPointBasis::Bind(IPAddressType aAddressType, const IPAddress & a sa.sin_port = htons(aPort); sa.sin_addr = aAddress.ToIPv4(); - if (bind(mSocket.GetFD(), reinterpret_cast(&sa), static_cast(sizeof(sa))) != 0) + if (bind(mSocket, reinterpret_cast(&sa), static_cast(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 == CHIP_NO_ERROR) - setsockopt(mSocket.GetFD(), IPPROTO_IP, IP_MULTICAST_IF, &sa, sizeof(sa)); + 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.GetFD(), IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); + setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); #endif // defined(IP_MULTICAST_TTL) // Allow socket transmitting broadcast packets. if (lRetval == CHIP_NO_ERROR) - setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable)); + setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable)); } #endif // INET_CONFIG_ENABLE_IPV4 else @@ -758,7 +758,7 @@ CHIP_ERROR IPEndPointBasis::BindInterface(IPAddressType aAddressType, InterfaceI if (aInterfaceId == INET_NULL_INTERFACEID) { // Stop interface-based filtering. - if (setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_BINDTODEVICE, "", 0) == -1) + if (setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, "", 0) == -1) { lRetval = chip::System::MapErrorPOSIX(errno); } @@ -774,7 +774,7 @@ CHIP_ERROR IPEndPointBasis::BindInterface(IPAddressType aAddressType, InterfaceI } if (lRetval == CHIP_NO_ERROR && - setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_BINDTODEVICE, lInterfaceName, socklen_t(strlen(lInterfaceName))) == -1) + setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, lInterfaceName, socklen_t(strlen(lInterfaceName))) == -1) { lRetval = chip::System::MapErrorPOSIX(errno); } @@ -907,7 +907,7 @@ CHIP_ERROR IPEndPointBasis::SendMsg(const IPPacketInfo * aPktInfo, chip::System: } // Send IP packet. - const ssize_t lenSent = sendmsg(mSocket.GetFD(), &msgHeader, 0); + const ssize_t lenSent = sendmsg(mSocket, &msgHeader, 0); if (lenSent == -1) return chip::System::MapErrorPOSIX(errno); if (lenSent != aBuffer->DataLength()) @@ -917,7 +917,7 @@ CHIP_ERROR IPEndPointBasis::SendMsg(const IPPacketInfo * aPktInfo, chip::System: CHIP_ERROR IPEndPointBasis::GetSocket(IPAddressType aAddressType, int aType, int aProtocol) { - if (!mSocket.HasFD()) + if (mSocket == INET_INVALID_SOCKET_FD) { const int one = 1; int family; @@ -938,10 +938,10 @@ CHIP_ERROR IPEndPointBasis::GetSocket(IPAddressType aAddressType, int aType, int return INET_ERROR_WRONG_ADDRESS_TYPE; } - const int fd = ::socket(family, aType, aProtocol); - if (fd == -1) + mSocket = ::socket(family, aType, aProtocol); + if (mSocket == -1) return chip::System::MapErrorPOSIX(errno); - ReturnErrorOnFailure(mSocket.Attach(fd)); + ReturnErrorOnFailure(SystemLayer().StartWatchingSocket(mSocket, &mWatch)); mAddrType = aAddressType; @@ -954,11 +954,11 @@ CHIP_ERROR IPEndPointBasis::GetSocket(IPAddressType aAddressType, int aType, int // logic up to check for implementations of these options and // to provide appropriate HAVE_xxxxx definitions accordingly. - int res = setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + int res = setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); static_cast(res); #ifdef SO_REUSEPORT - res = setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); + res = setsockopt(mSocket, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); if (res != 0) { ChipLogError(Inet, "SO_REUSEPORT failed: %d", errno); @@ -972,7 +972,7 @@ CHIP_ERROR IPEndPointBasis::GetSocket(IPAddressType aAddressType, int aType, int #ifdef IPV6_V6ONLY if (aAddressType == kIPAddressType_IPv6) { - res = setsockopt(mSocket.GetFD(), IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); + res = setsockopt(mSocket, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); if (res != 0) { ChipLogError(Inet, "IPV6_V6ONLY failed: %d", errno); @@ -984,7 +984,7 @@ CHIP_ERROR IPEndPointBasis::GetSocket(IPAddressType aAddressType, int aType, int #ifdef IP_PKTINFO if (aAddressType == kIPAddressType_IPv4) { - res = setsockopt(mSocket.GetFD(), IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); + res = setsockopt(mSocket, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); if (res != 0) { ChipLogError(Inet, "IP_PKTINFO failed: %d", errno); @@ -996,7 +996,7 @@ CHIP_ERROR IPEndPointBasis::GetSocket(IPAddressType aAddressType, int aType, int #ifdef IPV6_RECVPKTINFO if (aAddressType == kIPAddressType_IPv6) { - res = setsockopt(mSocket.GetFD(), IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); + res = setsockopt(mSocket, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)); if (res != 0) { ChipLogError(Inet, "IPV6_PKTINFO failed: %d", errno); @@ -1010,7 +1010,7 @@ CHIP_ERROR IPEndPointBasis::GetSocket(IPAddressType aAddressType, int aType, int // SIGPIPEs on unconnected UDP sockets. #ifdef SO_NOSIGPIPE { - res = setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); + res = setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); if (res != 0) { ChipLogError(Inet, "SO_NOSIGPIPE failed: %d", errno); @@ -1058,7 +1058,7 @@ void IPEndPointBasis::HandlePendingIO(uint16_t aPort) msgHeader.msg_control = controlData; msgHeader.msg_controllen = sizeof(controlData); - ssize_t rcvLen = recvmsg(mSocket.GetFD(), &msgHeader, MSG_DONTWAIT); + ssize_t rcvLen = recvmsg(mSocket, &msgHeader, MSG_DONTWAIT); if (rcvLen < 0) { diff --git a/src/inet/InetLayer.cpp b/src/inet/InetLayer.cpp index 38ad186c74e6df..85548146e000d0 100644 --- a/src/inet/InetLayer.cpp +++ b/src/inet/InetLayer.cpp @@ -32,7 +32,7 @@ * * Raw network transport * * For BSD/POSIX Sockets (CHIP_SYSTEM_CONFIG_USE_SOCKETS), event readiness - * notification is handled via file descriptors, using System::WatchableSocket. + * notification is handled via file descriptors, using a System::Layer API. * * For LwIP (CHIP_SYSTEM_CONFIG_USE_LWIP), event readiness notification is handled * via events / messages and platform- and system-specific hooks for the event @@ -49,8 +49,6 @@ #include -#include - #include #include diff --git a/src/inet/RawEndPoint.cpp b/src/inet/RawEndPoint.cpp index 5704aa488173aa..4f80b1e23784e3 100644 --- a/src/inet/RawEndPoint.cpp +++ b/src/inet/RawEndPoint.cpp @@ -48,7 +48,6 @@ #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS -#include #if HAVE_SYS_SOCKET_H #include #endif // HAVE_SYS_SOCKET_H @@ -219,14 +218,13 @@ CHIP_ERROR RawEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, Int dispatch_queue_t dispatchQueue = SystemLayer().WatchableEventsManager().GetDispatchQueue(); if (dispatchQueue != nullptr) { - unsigned long fd = static_cast(mSocket.GetFD()); + unsigned long fd = static_cast(mSocket); mReadableSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatchQueue); ReturnErrorCodeIf(mReadableSource == nullptr, CHIP_ERROR_NO_MEMORY); dispatch_source_set_event_handler(mReadableSource, ^{ - this->mSocket.SetPendingIO(System::SocketEventFlags::kRead); - this->HandlePendingIO(); + this->HandlePendingIO(System::SocketEventFlags::kRead); }); dispatch_resume(mReadableSource); @@ -332,17 +330,17 @@ CHIP_ERROR RawEndPoint::BindIPv6LinkLocal(InterfaceId intfId, const IPAddress & goto ret; } - if (::setsockopt(mSocket.GetFD(), IPPROTO_IPV6, IPV6_MULTICAST_IF, &lIfIndex, sizeof(lIfIndex)) != 0) + if (::setsockopt(mSocket, IPPROTO_IPV6, IPV6_MULTICAST_IF, &lIfIndex, sizeof(lIfIndex)) != 0) { goto optfail; } - if (::setsockopt(mSocket.GetFD(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &sInt255, sizeof(sInt255)) != 0) + if (::setsockopt(mSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &sInt255, sizeof(sInt255)) != 0) { goto optfail; } - if (::setsockopt(mSocket.GetFD(), IPPROTO_IPV6, IPV6_UNICAST_HOPS, &sInt255, sizeof(sInt255)) != 0) + if (::setsockopt(mSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &sInt255, sizeof(sInt255)) != 0) { goto optfail; } @@ -352,7 +350,9 @@ CHIP_ERROR RawEndPoint::BindIPv6LinkLocal(InterfaceId intfId, const IPAddress & optfail: res = chip::System::MapErrorPOSIX(errno); - mSocket.Close(); + SystemLayer().StopWatchingSocket(&mWatch); + close(mSocket); + mSocket = INET_INVALID_SOCKET_FD; mAddrType = kIPAddressType_Unknown; #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS @@ -424,8 +424,8 @@ CHIP_ERROR RawEndPoint::Listen(IPEndPointBasis::OnMessageReceivedFunct onMessage #if CHIP_SYSTEM_CONFIG_USE_SOCKETS // Wait for ability to read on this endpoint. - mSocket.SetCallback(HandlePendingIO, reinterpret_cast(this)); - ReturnErrorOnFailure(mSocket.RequestCallbackOnPendingRead()); + ReturnErrorOnFailure(SystemLayer().SetCallback(mWatch, HandlePendingIO, reinterpret_cast(this))); + ReturnErrorOnFailure(SystemLayer().RequestCallbackOnPendingRead(mWatch)); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS return CHIP_NO_ERROR; @@ -465,15 +465,13 @@ void RawEndPoint::Close() #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - - if (mSocket.HasFD()) + if (mSocket != INET_INVALID_SOCKET_FD) { - mSocket.Close(); + SystemLayer().StopWatchingSocket(&mWatch); + close(mSocket); + mSocket = INET_INVALID_SOCKET_FD; } - // Clear any results from select() that indicate pending I/O for the socket. - mSocket.ClearPendingIO(); - #if CHIP_SYSTEM_CONFIG_USE_DISPATCH if (mReadableSource) { @@ -719,7 +717,7 @@ CHIP_ERROR RawEndPoint::SetICMPFilter(uint8_t numICMPTypes, const uint8_t * aICM { ICMP6_FILTER_SETPASSALL(&filter); } - if (setsockopt(mSocket.GetFD(), IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) == -1) + if (setsockopt(mSocket, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) == -1) { return chip::System::MapErrorPOSIX(errno); } @@ -1024,21 +1022,19 @@ CHIP_ERROR RawEndPoint::GetSocket(IPAddressType aAddressType) } // static -void RawEndPoint::HandlePendingIO(System::WatchableSocket & socket) +void RawEndPoint::HandlePendingIO(System::SocketEvents events, intptr_t data) { - reinterpret_cast(socket.GetCallbackData())->HandlePendingIO(); + reinterpret_cast(data)->HandlePendingIO(events); } -void RawEndPoint::HandlePendingIO() +void RawEndPoint::HandlePendingIO(System::SocketEvents events) { - if (mState == kState_Listening && OnMessageReceived != nullptr && mSocket.HasPendingRead()) + if (mState == kState_Listening && OnMessageReceived != nullptr && events.Has(System::SocketEventFlags::kRead)) { const uint16_t lPort = 0; IPEndPointBasis::HandlePendingIO(lPort); } - - mSocket.ClearPendingIO(); } #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS diff --git a/src/inet/RawEndPoint.h b/src/inet/RawEndPoint.h index 67992f3c9f2189..8d5f11d5c53134 100644 --- a/src/inet/RawEndPoint.h +++ b/src/inet/RawEndPoint.h @@ -112,8 +112,8 @@ class DLL_EXPORT RawEndPoint : public IPEndPointBasis #if CHIP_SYSTEM_CONFIG_USE_SOCKETS CHIP_ERROR GetSocket(IPAddressType addrType); - void HandlePendingIO(); - static void HandlePendingIO(System::WatchableSocket & socket); + void HandlePendingIO(System::SocketEvents events); + static void HandlePendingIO(System::SocketEvents events, intptr_t data); #if CHIP_SYSTEM_CONFIG_USE_DISPATCH dispatch_source_t mReadableSource = nullptr; diff --git a/src/inet/TCPEndPoint.cpp b/src/inet/TCPEndPoint.cpp index 2447639e471d07..ca4b28e62f6421 100644 --- a/src/inet/TCPEndPoint.cpp +++ b/src/inet/TCPEndPoint.cpp @@ -190,7 +190,7 @@ CHIP_ERROR TCPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uin if (res == CHIP_NO_ERROR && reuseAddr) { int n = 1; - setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)); + setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)); #ifdef SO_REUSEPORT // Enable SO_REUSEPORT. This permits coexistence between an @@ -203,7 +203,7 @@ CHIP_ERROR TCPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uin // e.g. two untargetted-listen CHIP clients, or two // targetted-listen CHIP clients with the same node id. - if (setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n)) != 0) + if (setsockopt(mSocket, SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n)) != 0) { ChipLogError(Inet, "SO_REUSEPORT: %d", errno); } @@ -222,7 +222,7 @@ CHIP_ERROR TCPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uin sa.sin6_addr = addr.ToIPv6(); sa.sin6_scope_id = 0; - if (bind(mSocket.GetFD(), reinterpret_cast(&sa), static_cast(sizeof(sa))) != 0) + if (bind(mSocket, reinterpret_cast(&sa), static_cast(sizeof(sa))) != 0) res = chip::System::MapErrorPOSIX(errno); } #if INET_CONFIG_ENABLE_IPV4 @@ -234,7 +234,7 @@ CHIP_ERROR TCPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uin sa.sin_port = htons(port); sa.sin_addr = addr.ToIPv4(); - if (bind(mSocket.GetFD(), reinterpret_cast(&sa), static_cast(sizeof(sa))) != 0) + if (bind(mSocket, reinterpret_cast(&sa), static_cast(sizeof(sa))) != 0) res = chip::System::MapErrorPOSIX(errno); } #endif // INET_CONFIG_ENABLE_IPV4 @@ -246,7 +246,7 @@ CHIP_ERROR TCPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uin dispatch_queue_t dispatchQueue = SystemLayer().WatchableEventsManager().GetDispatchQueue(); if (dispatchQueue != nullptr) { - unsigned long fd = static_cast(mSocket.GetFD()); + unsigned long fd = static_cast(mSocket); mReadableSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatchQueue); ReturnErrorCodeIf(mReadableSource == nullptr, CHIP_ERROR_NO_MEMORY); @@ -255,13 +255,11 @@ CHIP_ERROR TCPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uin ReturnErrorCodeIf(mWriteableSource == nullptr, CHIP_ERROR_NO_MEMORY); dispatch_source_set_event_handler(mReadableSource, ^{ - this->mSocket.SetPendingIO(System::SocketEventFlags::kRead); - this->HandlePendingIO(); + this->HandlePendingIO(System::SocketEventFlags::kRead); }); dispatch_source_set_event_handler(mWriteableSource, ^{ - this->mSocket.SetPendingIO(System::SocketEventFlags::kWrite); - this->HandlePendingIO(); + this->HandlePendingIO(System::SocketEventFlags::kWrite); }); dispatch_resume(mReadableSource); @@ -299,19 +297,22 @@ CHIP_ERROR TCPEndPoint::Listen(uint16_t backlog) #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - if (listen(mSocket.GetFD(), backlog) != 0) + if (listen(mSocket, backlog) != 0) { res = chip::System::MapErrorPOSIX(errno); } else { // Enable non-blocking mode for the socket. - int flags = fcntl(mSocket.GetFD(), F_GETFL, 0); - fcntl(mSocket.GetFD(), F_SETFL, flags | O_NONBLOCK); + int flags = fcntl(mSocket, F_GETFL, 0); + fcntl(mSocket, F_SETFL, flags | O_NONBLOCK); // Wait for ability to read on this endpoint. - mSocket.SetCallback(HandlePendingIO, reinterpret_cast(this)); - res = mSocket.RequestCallbackOnPendingRead(); + res = SystemLayer().SetCallback(mWatch, HandlePendingIO, reinterpret_cast(this)); + if (res == CHIP_NO_ERROR) + { + res = SystemLayer().RequestCallbackOnPendingRead(mWatch); + } } #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS @@ -445,7 +446,7 @@ CHIP_ERROR TCPEndPoint::Connect(const IPAddress & addr, uint16_t port, Interface // 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.GetFD(), SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)); + int r = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)); if (r < 0 && errno != EACCES) { return res = chip::System::MapErrorPOSIX(errno); @@ -467,12 +468,12 @@ CHIP_ERROR TCPEndPoint::Connect(const IPAddress & addr, uint16_t port, Interface // Disable generation of SIGPIPE. #ifdef SO_NOSIGPIPE int n = 1; - setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_NOSIGPIPE, &n, sizeof(n)); + setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &n, sizeof(n)); #endif // defined(SO_NOSIGPIPE) // Enable non-blocking mode for the socket. - int flags = fcntl(mSocket.GetFD(), F_GETFL, 0); - fcntl(mSocket.GetFD(), F_SETFL, flags | O_NONBLOCK); + int flags = fcntl(mSocket, F_GETFL, 0); + fcntl(mSocket, F_SETFL, flags | O_NONBLOCK); socklen_t sockaddrsize = 0; const sockaddr * sockaddrptr = nullptr; @@ -510,7 +511,7 @@ CHIP_ERROR TCPEndPoint::Connect(const IPAddress & addr, uint16_t port, Interface else return INET_ERROR_WRONG_ADDRESS_TYPE; - int conRes = connect(mSocket.GetFD(), sockaddrptr, sockaddrsize); + int conRes = connect(mSocket, sockaddrptr, sockaddrsize); if (conRes == -1 && errno != EINPROGRESS) { @@ -519,7 +520,7 @@ CHIP_ERROR TCPEndPoint::Connect(const IPAddress & addr, uint16_t port, Interface return res; } - mSocket.SetCallback(HandlePendingIO, reinterpret_cast(this)); + ReturnErrorOnFailure(SystemLayer().SetCallback(mWatch, HandlePendingIO, reinterpret_cast(this))); // Once Connecting or Connected, bump the reference count. The corresponding Release() // [or on LwIP, DeferredRelease()] will happen in DoClose(). @@ -529,7 +530,7 @@ CHIP_ERROR TCPEndPoint::Connect(const IPAddress & addr, uint16_t port, Interface { State = kState_Connected; // Wait for ability to read on this endpoint. - ReturnErrorOnFailure(mSocket.RequestCallbackOnPendingRead()); + ReturnErrorOnFailure(SystemLayer().RequestCallbackOnPendingRead(mWatch)); if (OnConnectComplete != nullptr) OnConnectComplete(this, CHIP_NO_ERROR); } @@ -537,7 +538,7 @@ CHIP_ERROR TCPEndPoint::Connect(const IPAddress & addr, uint16_t port, Interface { State = kState_Connecting; // Wait for ability to write on this endpoint. - ReturnErrorOnFailure(mSocket.RequestCallbackOnPendingWrite()); + ReturnErrorOnFailure(SystemLayer().RequestCallbackOnPendingWrite(mWatch)); } #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS @@ -633,7 +634,7 @@ CHIP_ERROR TCPEndPoint::GetPeerInfo(IPAddress * retAddr, uint16_t * retPort) con memset(&sa, 0, sizeof(sa)); socklen_t saLen = sizeof(sa); - if (getpeername(mSocket.GetFD(), &sa.any, &saLen) != 0) + if (getpeername(mSocket, &sa.any, &saLen) != 0) return chip::System::MapErrorPOSIX(errno); if (sa.any.sa_family == AF_INET6) @@ -704,7 +705,7 @@ CHIP_ERROR TCPEndPoint::GetLocalInfo(IPAddress * retAddr, uint16_t * retPort) memset(&sa, 0, sizeof(sa)); socklen_t saLen = sizeof(sa); - if (getsockname(mSocket.GetFD(), &sa.any, &saLen) != 0) + if (getsockname(mSocket, &sa.any, &saLen) != 0) return chip::System::MapErrorPOSIX(errno); if (sa.any.sa_family == AF_INET6) @@ -753,7 +754,7 @@ CHIP_ERROR TCPEndPoint::GetInterfaceId(InterfaceId * retInterface) memset(&sa, 0, sizeof(sa)); socklen_t saLen = sizeof(sa); - if (getpeername(mSocket.GetFD(), &sa.any, &saLen) != 0) + if (getpeername(mSocket, &sa.any, &saLen) != 0) { return chip::System::MapErrorPOSIX(errno); } @@ -802,7 +803,7 @@ CHIP_ERROR TCPEndPoint::Send(System::PacketBufferHandle && data, bool push) mSendQueue = std::move(data); #if CHIP_SYSTEM_CONFIG_USE_SOCKETS // Wait for ability to write on this endpoint. - ReturnErrorOnFailure(mSocket.RequestCallbackOnPendingWrite()); + ReturnErrorOnFailure(SystemLayer().RequestCallbackOnPendingWrite(mWatch)); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS } else @@ -884,7 +885,7 @@ CHIP_ERROR TCPEndPoint::EnableNoDelay() #ifdef TCP_NODELAY // Disable TCP Nagle buffering by setting TCP_NODELAY socket option to true val = 1; - if (setsockopt(mSocket.GetFD(), TCP_SOCKOPT_LEVEL, TCP_NODELAY, &val, sizeof(val)) != 0) + if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_NODELAY, &val, sizeof(val)) != 0) return chip::System::MapErrorPOSIX(errno); #endif // defined(TCP_NODELAY) } @@ -942,22 +943,22 @@ CHIP_ERROR TCPEndPoint::EnableKeepAlive(uint16_t interval, uint16_t timeoutCount // Set the idle interval val = interval; - if (setsockopt(mSocket.GetFD(), TCP_SOCKOPT_LEVEL, TCP_IDLE_INTERVAL_OPT_NAME, &val, sizeof(val)) != 0) + 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.GetFD(), TCP_SOCKOPT_LEVEL, TCP_KEEPINTVL, &val, sizeof(val)) != 0) + 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.GetFD(), TCP_SOCKOPT_LEVEL, TCP_KEEPCNT, &val, sizeof(val)) != 0) + 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.GetFD(), SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0) + if (setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0) return chip::System::MapErrorPOSIX(errno); } @@ -1018,7 +1019,7 @@ CHIP_ERROR TCPEndPoint::DisableKeepAlive() // Disable keepalives on the connection. val = 0; // disable - if (setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0) + if (setsockopt(mSocket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0) return chip::System::MapErrorPOSIX(errno); } @@ -1068,7 +1069,7 @@ CHIP_ERROR TCPEndPoint::SetUserTimeout(uint32_t userTimeoutMillis) #if defined(TCP_USER_TIMEOUT) // Set the user timeout uint32_t val = userTimeoutMillis; - if (setsockopt(mSocket.GetFD(), TCP_SOCKOPT_LEVEL, TCP_USER_TIMEOUT, &val, sizeof(val)) != 0) + if (setsockopt(mSocket, TCP_SOCKOPT_LEVEL, TCP_USER_TIMEOUT, &val, sizeof(val)) != 0) return chip::System::MapErrorPOSIX(errno); #else // TCP_USER_TIMEOUT res = CHIP_ERROR_NOT_IMPLEMENTED; @@ -1394,7 +1395,7 @@ CHIP_ERROR TCPEndPoint::DriveSending() { uint16_t bufLen = mSendQueue->DataLength(); - ssize_t lenSentRaw = send(mSocket.GetFD(), mSendQueue->Start(), bufLen, sendFlags); + ssize_t lenSentRaw = send(mSocket, mSendQueue->Start(), bufLen, sendFlags); if (lenSentRaw == -1) { @@ -1425,7 +1426,7 @@ CHIP_ERROR TCPEndPoint::DriveSending() if (mSendQueue.IsNull()) { // Do not wait for ability to write on this endpoint. - err = mSocket.ClearCallbackOnPendingWrite(); + err = SystemLayer().ClearCallbackOnPendingWrite(mWatch); if (err != CHIP_NO_ERROR) { break; @@ -1478,7 +1479,7 @@ CHIP_ERROR TCPEndPoint::DriveSending() // If we're in the SendShutdown state and the send queue is now empty, shutdown writing on the socket. if (State == kState_SendShutdown && mSendQueue.IsNull()) { - if (shutdown(mSocket.GetFD(), SHUT_WR) != 0) + if (shutdown(mSocket, SHUT_WR) != 0) err = chip::System::MapErrorPOSIX(errno); } } @@ -1532,10 +1533,10 @@ void TCPEndPoint::HandleConnectComplete(CHIP_ERROR err) #if CHIP_SYSTEM_CONFIG_USE_SOCKETS // Wait for ability to read or write on this endpoint. - err = mSocket.RequestCallbackOnPendingRead(); + err = SystemLayer().RequestCallbackOnPendingRead(mWatch); if (err == CHIP_NO_ERROR) { - err = mSocket.RequestCallbackOnPendingWrite(); + err = SystemLayer().RequestCallbackOnPendingWrite(mWatch); } if (err != CHIP_NO_ERROR) { @@ -1653,7 +1654,7 @@ CHIP_ERROR TCPEndPoint::DoClose(CHIP_ERROR err, bool suppressCallback) #if CHIP_SYSTEM_CONFIG_USE_SOCKETS // If the socket hasn't been closed already... - if (mSocket.HasFD()) + 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 @@ -1666,11 +1667,13 @@ CHIP_ERROR TCPEndPoint::DoClose(CHIP_ERROR err, bool suppressCallback) lingerStruct.l_onoff = 1; lingerStruct.l_linger = 0; - if (setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_LINGER, &lingerStruct, sizeof(lingerStruct)) != 0) + if (setsockopt(mSocket, SOL_SOCKET, SO_LINGER, &lingerStruct, sizeof(lingerStruct)) != 0) ChipLogError(Inet, "SO_LINGER: %d", errno); } - mSocket.Close(); + SystemLayer().StopWatchingSocket(&mWatch); + close(mSocket); + mSocket = INET_INVALID_SOCKET_FD; } } @@ -1687,9 +1690,6 @@ CHIP_ERROR TCPEndPoint::DoClose(CHIP_ERROR err, bool suppressCallback) } #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH - // Clear any results from select() that indicate pending I/O for the socket. - mSocket.ClearPendingIO(); - #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS #if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT @@ -2423,7 +2423,7 @@ CHIP_ERROR TCPEndPoint::BindSrcAddrFromIntf(IPAddressType addrType, InterfaceId CHIP_ERROR TCPEndPoint::GetSocket(IPAddressType addrType) { - if (!mSocket.HasFD()) + if (mSocket == INET_INVALID_SOCKET_FD) { int family; if (addrType == kIPAddressType_IPv6) @@ -2434,10 +2434,10 @@ CHIP_ERROR TCPEndPoint::GetSocket(IPAddressType addrType) #endif // INET_CONFIG_ENABLE_IPV4 else return INET_ERROR_WRONG_ADDRESS_TYPE; - const int fd = ::socket(family, SOCK_STREAM | SOCK_FLAGS, 0); - if (fd == -1) + mSocket = ::socket(family, SOCK_STREAM | SOCK_FLAGS, 0); + if (mSocket == -1) return chip::System::MapErrorPOSIX(errno); - ReturnErrorOnFailure(mSocket.Attach(fd)); + ReturnErrorOnFailure(SystemLayer().StartWatchingSocket(mSocket, &mWatch)); mAddrType = addrType; // If creating an IPv6 socket, tell the kernel that it will be IPv6 only. This makes it @@ -2446,7 +2446,7 @@ CHIP_ERROR TCPEndPoint::GetSocket(IPAddressType addrType) if (family == PF_INET6) { int one = 1; - setsockopt(mSocket.GetFD(), IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); + setsockopt(mSocket, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); } #endif // defined(IPV6_V6ONLY) @@ -2455,7 +2455,7 @@ CHIP_ERROR TCPEndPoint::GetSocket(IPAddressType addrType) #ifdef SO_NOSIGPIPE { int one = 1; - int res = setsockopt(mSocket.GetFD(), SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); + int res = setsockopt(mSocket, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); if (res != 0) { ChipLogError(Inet, "SO_NOSIGPIPE: %d", errno); @@ -2472,12 +2472,12 @@ CHIP_ERROR TCPEndPoint::GetSocket(IPAddressType addrType) } // static -void TCPEndPoint::HandlePendingIO(System::WatchableSocket & socket) +void TCPEndPoint::HandlePendingIO(System::SocketEvents events, intptr_t data) { - reinterpret_cast(socket.GetCallbackData())->HandlePendingIO(); + reinterpret_cast(data)->HandlePendingIO(events); } -void TCPEndPoint::HandlePendingIO() +void TCPEndPoint::HandlePendingIO(System::SocketEvents events) { // Prevent the end point from being freed while in the middle of a callback. Retain(); @@ -2486,7 +2486,7 @@ void TCPEndPoint::HandlePendingIO() // ready to be received on the socket, process the incoming connection. if (State == kState_Listening) { - if (OnConnectionReceived != nullptr && mSocket.HasPendingRead()) + if (OnConnectionReceived != nullptr && events.Has(System::SocketEventFlags::kRead)) { HandleIncomingConnection(); } @@ -2496,13 +2496,13 @@ void TCPEndPoint::HandlePendingIO() else if (State == kState_Connecting) { // The socket being writable indicates the connection has completed (successfully or otherwise). - if (mSocket.HasPendingWrite()) + if (events.Has(System::SocketEventFlags::kWrite)) { #if !__MBED__ // Get the connection result from the socket. int osConRes; socklen_t optLen = sizeof(osConRes); - if (getsockopt(mSocket.GetFD(), SOL_SOCKET, SO_ERROR, &osConRes, &optLen) != 0) + if (getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &osConRes, &optLen) != 0) osConRes = errno; #else // On Mbed OS, connect blocks and never returns EINPROGRESS @@ -2520,18 +2520,16 @@ void TCPEndPoint::HandlePendingIO() { // 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.IsNull() && mSocket.HasPendingWrite()) + if (IsConnected() && !mSendQueue.IsNull() && events.Has(System::SocketEventFlags::kWrite)) 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 != nullptr && - mSocket.HasPendingRead()) + events.Has(System::SocketEventFlags::kRead)) ReceiveData(); } - mSocket.ClearPendingIO(); - Release(); } @@ -2563,7 +2561,7 @@ void TCPEndPoint::ReceiveData() } // Attempt to receive data from the socket. - ssize_t rcvLen = recv(mSocket.GetFD(), rcvBuf->Start() + rcvBuf->DataLength(), rcvBuf->AvailableDataLength(), 0); + ssize_t rcvLen = recv(mSocket, rcvBuf->Start() + rcvBuf->DataLength(), rcvBuf->AvailableDataLength(), 0); #if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT CHIP_ERROR err; @@ -2635,7 +2633,7 @@ void TCPEndPoint::ReceiveData() else State = kState_Closing; // Do not wait for ability to read on this endpoint. - (void) mSocket.ClearCallbackOnPendingRead(); + (void) SystemLayer().ClearCallbackOnPendingRead(mWatch); // Call the app's OnPeerClose. if (OnPeerClose != nullptr) OnPeerClose(this); @@ -2684,7 +2682,7 @@ void TCPEndPoint::HandleIncomingConnection() socklen_t saLen = sizeof(sa); // Accept the new connection. - int conSocket = accept(mSocket.GetFD(), &sa.any, &saLen); + int conSocket = accept(mSocket, &sa.any, &saLen); if (conSocket == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) @@ -2732,7 +2730,8 @@ void TCPEndPoint::HandleIncomingConnection() if (err == CHIP_NO_ERROR) { // Put the new end point into the Connected state. - err = conEP->mSocket.Attach(conSocket); + conEP->mSocket = conSocket; + err = SystemLayer().StartWatchingSocket(conSocket, &conEP->mWatch); if (err == CHIP_NO_ERROR) { conEP->State = kState_Connected; @@ -2744,8 +2743,11 @@ void TCPEndPoint::HandleIncomingConnection() conEP->Retain(); // Wait for ability to read on this endpoint. - conEP->mSocket.SetCallback(HandlePendingIO, reinterpret_cast(conEP)); - err = conEP->mSocket.RequestCallbackOnPendingRead(); + err = conEP->SystemLayer().SetCallback(conEP->mWatch, HandlePendingIO, reinterpret_cast(conEP)); + if (err == CHIP_NO_ERROR) + { + err = conEP->SystemLayer().RequestCallbackOnPendingRead(conEP->mWatch); + } if (err == CHIP_NO_ERROR) { // Call the app's callback function. @@ -2780,7 +2782,7 @@ CHIP_ERROR TCPEndPoint::CheckConnectionProgress(bool & isProgressing) // Fetch the bytes pending successful transmission in the TCP out queue. - if (ioctl(mSocket.GetFD(), TIOCOUTQ, &currPendingBytesRaw) < 0) + if (ioctl(mSocket, TIOCOUTQ, &currPendingBytesRaw) < 0) { return chip::System::MapErrorPOSIX(errno); } diff --git a/src/inet/TCPEndPoint.h b/src/inet/TCPEndPoint.h index 853bc2538ef419..a8e46174293c3a 100644 --- a/src/inet/TCPEndPoint.h +++ b/src/inet/TCPEndPoint.h @@ -688,11 +688,11 @@ class DLL_EXPORT TCPEndPoint : public EndPointBasis #if CHIP_SYSTEM_CONFIG_USE_SOCKETS CHIP_ERROR GetSocket(IPAddressType addrType); - void HandlePendingIO(); + void HandlePendingIO(System::SocketEvents events); void ReceiveData(); void HandleIncomingConnection(); CHIP_ERROR BindSrcAddrFromIntf(IPAddressType addrType, InterfaceId intfId); - static void HandlePendingIO(System::WatchableSocket & socket); + static void HandlePendingIO(System::SocketEvents events, intptr_t data); #if CHIP_SYSTEM_CONFIG_USE_DISPATCH dispatch_source_t mReadableSource = nullptr; diff --git a/src/inet/UDPEndPoint.cpp b/src/inet/UDPEndPoint.cpp index ffcdac7b645536..613f543f6a848c 100644 --- a/src/inet/UDPEndPoint.cpp +++ b/src/inet/UDPEndPoint.cpp @@ -232,7 +232,7 @@ CHIP_ERROR UDPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uin } boundAddr; socklen_t boundAddrLen = sizeof(boundAddr); - if (getsockname(mSocket.GetFD(), &boundAddr.any, &boundAddrLen) == 0) + if (getsockname(mSocket, &boundAddr.any, &boundAddrLen) == 0) { if (boundAddr.any.sa_family == AF_INET) { @@ -249,14 +249,13 @@ CHIP_ERROR UDPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uin dispatch_queue_t dispatchQueue = SystemLayer().WatchableEventsManager().GetDispatchQueue(); if (dispatchQueue != nullptr) { - unsigned long fd = static_cast(mSocket.GetFD()); + unsigned long fd = static_cast(mSocket); mReadableSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatchQueue); ReturnErrorCodeIf(mReadableSource == nullptr, CHIP_ERROR_NO_MEMORY); dispatch_source_set_event_handler(mReadableSource, ^{ - this->mSocket.SetPendingIO(System::SocketEventFlags::kRead); - this->HandlePendingIO(); + this->HandlePendingIO(System::SocketEventFlags::kRead); }); dispatch_resume(mReadableSource); } @@ -350,8 +349,8 @@ CHIP_ERROR UDPEndPoint::Listen(OnMessageReceivedFunct onMessageReceived, OnRecei #if CHIP_SYSTEM_CONFIG_USE_SOCKETS // Wait for ability to read on this endpoint. - mSocket.SetCallback(HandlePendingIO, reinterpret_cast(this)); - ReturnErrorOnFailure(mSocket.RequestCallbackOnPendingRead()); + ReturnErrorOnFailure(SystemLayer().SetCallback(mWatch, HandlePendingIO, reinterpret_cast(this))); + ReturnErrorOnFailure(SystemLayer().RequestCallbackOnPendingRead(mWatch)); #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS return CHIP_NO_ERROR; @@ -392,14 +391,13 @@ void UDPEndPoint::Close() #if CHIP_SYSTEM_CONFIG_USE_SOCKETS - if (mSocket.HasFD()) + if (mSocket != INET_INVALID_SOCKET_FD) { - mSocket.Close(); + SystemLayer().StopWatchingSocket(&mWatch); + close(mSocket); + mSocket = INET_INVALID_SOCKET_FD; } - // Clear any results from select() that indicate pending I/O for the socket. - mSocket.ClearPendingIO(); - #if CHIP_SYSTEM_CONFIG_USE_DISPATCH if (mReadableSource) { @@ -907,21 +905,19 @@ CHIP_ERROR UDPEndPoint::GetSocket(IPAddressType aAddressType) } // static -void UDPEndPoint::HandlePendingIO(System::WatchableSocket & socket) +void UDPEndPoint::HandlePendingIO(System::SocketEvents events, intptr_t data) { - reinterpret_cast(socket.GetCallbackData())->HandlePendingIO(); + reinterpret_cast(data)->HandlePendingIO(events); } -void UDPEndPoint::HandlePendingIO() +void UDPEndPoint::HandlePendingIO(System::SocketEvents events) { - if (mState == kState_Listening && OnMessageReceived != nullptr && mSocket.HasPendingRead()) + if (mState == kState_Listening && OnMessageReceived != nullptr && events.Has(System::SocketEventFlags::kRead)) { const uint16_t lPort = mBoundPort; IPEndPointBasis::HandlePendingIO(lPort); } - - mSocket.ClearPendingIO(); } #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS diff --git a/src/inet/UDPEndPoint.h b/src/inet/UDPEndPoint.h index b2549a1b4f3db0..89ec55467d46f0 100644 --- a/src/inet/UDPEndPoint.h +++ b/src/inet/UDPEndPoint.h @@ -91,8 +91,8 @@ class DLL_EXPORT UDPEndPoint : public IPEndPointBasis uint16_t mBoundPort; CHIP_ERROR GetSocket(IPAddressType addrType); - void HandlePendingIO(); - static void HandlePendingIO(System::WatchableSocket & socket); + void HandlePendingIO(System::SocketEvents events); + static void HandlePendingIO(System::SocketEvents events, intptr_t data); #if CHIP_SYSTEM_CONFIG_USE_DISPATCH dispatch_source_t mReadableSource = nullptr; diff --git a/src/inet/tests/TestInetCommonPosix.cpp b/src/inet/tests/TestInetCommonPosix.cpp index 71cc2dde2611a9..4ba1b89278fd13 100644 --- a/src/inet/tests/TestInetCommonPosix.cpp +++ b/src/inet/tests/TestInetCommonPosix.cpp @@ -471,11 +471,11 @@ void ServiceEvents(uint32_t aSleepTimeMilliseconds) #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS #if CHIP_SYSTEM_CONFIG_USE_LWIP - if (gSystemLayer.State() == System::kLayerState_Initialized) + if (gSystemLayer.State() == System::LayerState::kInitialized) { static uint32_t sRemainingSystemLayerEventDelay = 0; - if (gSystemLayer.State() == System::kLayerState_Initialized) + if (gSystemLayer.State() == System::LayerState::kInitialized) { if (sRemainingSystemLayerEventDelay == 0) { diff --git a/src/inet/tests/TestInetEndPoint.cpp b/src/inet/tests/TestInetEndPoint.cpp index 90b0cbe7e1cdf0..21d1b457f95df5 100644 --- a/src/inet/tests/TestInetEndPoint.cpp +++ b/src/inet/tests/TestInetEndPoint.cpp @@ -44,7 +44,6 @@ #include #include -#include #include @@ -497,7 +496,6 @@ static void TestInetEndPointLimit(nlTestSuite * inSuite, void * inContext) UDPEndPoint * testUDPEP = nullptr; TCPEndPoint * testTCPEP = nullptr; CHIP_ERROR err; - char numTimersTest[CHIP_SYSTEM_CONFIG_NUM_TIMERS + 1]; #if INET_CONFIG_ENABLE_RAW_ENDPOINT for (int i = 0; i < INET_CONFIG_NUM_RAW_ENDPOINTS + 1; i++) @@ -520,9 +518,12 @@ static void TestInetEndPointLimit(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); } +#if CHIP_SYSTEM_CONFIG_USE_TIMER_POOL + char numTimersTest[CHIP_SYSTEM_CONFIG_NUM_TIMERS + 1]; for (int i = 0; i < CHIP_SYSTEM_CONFIG_NUM_TIMERS + 1; i++) err = gSystemLayer.StartTimer(10, HandleTimer, &numTimersTest[i]); NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_NO_MEMORY); +#endif // CHIP_SYSTEM_CONFIG_USE_TIMER_POOL ShutdownNetwork(); ShutdownSystemLayer(); diff --git a/src/inet/tests/TestInetLayer.cpp b/src/inet/tests/TestInetLayer.cpp index ddbe1917fc2622..86509c534c07c5 100644 --- a/src/inet/tests/TestInetLayer.cpp +++ b/src/inet/tests/TestInetLayer.cpp @@ -40,8 +40,6 @@ #include #include -#include - #include "TestInetCommon.h" #include "TestInetCommonOptions.h" #include "TestInetLayerCommon.hpp" diff --git a/src/inet/tests/TestInetLayerDNS.cpp b/src/inet/tests/TestInetLayerDNS.cpp index 8ea2a8437ff40e..c25bcc1cab9966 100644 --- a/src/inet/tests/TestInetLayerDNS.cpp +++ b/src/inet/tests/TestInetLayerDNS.cpp @@ -41,7 +41,6 @@ #include #include -#include #include "TestInetCommon.h" #include "TestSetupSignalling.h" diff --git a/src/inet/tests/TestInetLayerMulticast.cpp b/src/inet/tests/TestInetLayerMulticast.cpp index 6a03656721a6e5..4fa581030e096d 100644 --- a/src/inet/tests/TestInetLayerMulticast.cpp +++ b/src/inet/tests/TestInetLayerMulticast.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include "TestInetCommon.h" #include "TestInetCommonOptions.h" diff --git a/src/messaging/ExchangeContext.cpp b/src/messaging/ExchangeContext.cpp index ade6f2639b930c..e416ac937e6e4d 100644 --- a/src/messaging/ExchangeContext.cpp +++ b/src/messaging/ExchangeContext.cpp @@ -42,7 +42,6 @@ #include #include #include -#include using namespace chip::Encoding; using namespace chip::Inet; diff --git a/src/messaging/ExchangeContext.h b/src/messaging/ExchangeContext.h index 2ac3565642e6cd..a34a15fd2f5d53 100644 --- a/src/messaging/ExchangeContext.h +++ b/src/messaging/ExchangeContext.h @@ -33,7 +33,6 @@ #include #include #include -#include #include namespace chip { diff --git a/src/messaging/ReliableMessageMgr.h b/src/messaging/ReliableMessageMgr.h index 81ed09cfdbde96..088bd13124e659 100644 --- a/src/messaging/ReliableMessageMgr.h +++ b/src/messaging/ReliableMessageMgr.h @@ -34,7 +34,6 @@ #include #include #include -#include #include namespace chip { diff --git a/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp b/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp index 94422fa8ca3cc7..468b16e5cf1c98 100644 --- a/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp +++ b/src/platform/ESP32/bluedroid/BLEManagerImpl.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include "esp_bt.h" #include "esp_bt_main.h" diff --git a/src/platform/Linux/MdnsImpl.cpp b/src/platform/Linux/MdnsImpl.cpp index 3ac48d30eeb57a..f3a81cb86b1997 100644 --- a/src/platform/Linux/MdnsImpl.cpp +++ b/src/platform/Linux/MdnsImpl.cpp @@ -88,10 +88,11 @@ AvahiWatchEvent ToAvahiWatchEvent(SocketEvents events) (events.Has(chip::System::SocketEventFlags::kError) ? AVAHI_WATCH_ERR : 0)); } -void AvahiWatchCallbackTrampoline(chip::System::WatchableSocket & socket) +void AvahiWatchCallbackTrampoline(chip::System::SocketEvents events, intptr_t data) { - AvahiWatch * const watch = reinterpret_cast(socket.GetCallbackData()); - watch->mCallback(watch, socket.GetFD(), ToAvahiWatchEvent(socket.GetPendingEvents()), watch->mContext); + AvahiWatch * const watch = reinterpret_cast(data); + watch->mPendingIO = ToAvahiWatchEvent(events); + watch->mCallback(watch, watch->mSocket, watch->mPendingIO, watch->mContext); } CHIP_ERROR MakeAvahiStringListFromTextEntries(TextEntry * entries, size_t size, AvahiStringList ** strListOut) @@ -163,17 +164,10 @@ AvahiWatch * Poller::WatchNew(int fd, AvahiWatchEvent event, AvahiWatchCallback VerifyOrDie(callback != nullptr && fd >= 0); auto watch = std::make_unique(); - watch->mSocket.Init(*mWatchableEvents); - LogErrorOnFailure(watch->mSocket.Attach(fd)); - watch->mSocket.SetCallback(AvahiWatchCallbackTrampoline, reinterpret_cast(watch.get())); - if (event & AVAHI_WATCH_IN) - { - LogErrorOnFailure(watch->mSocket.RequestCallbackOnPendingRead()); - } - if (event & AVAHI_WATCH_OUT) - { - LogErrorOnFailure(watch->mSocket.RequestCallbackOnPendingWrite()); - } + watch->mSocket = fd; + LogErrorOnFailure(DeviceLayer::SystemLayer.StartWatchingSocket(fd, &watch->mSocketWatch)); + LogErrorOnFailure(DeviceLayer::SystemLayer.SetCallback(watch->mSocketWatch, AvahiWatchCallbackTrampoline, reinterpret_cast(watch.get()))); + WatchUpdate(watch.get(), event); watch->mCallback = callback; watch->mContext = context; watch->mPoller = this; @@ -186,25 +180,25 @@ void Poller::WatchUpdate(AvahiWatch * watch, AvahiWatchEvent event) { if (event & AVAHI_WATCH_IN) { - LogErrorOnFailure(watch->mSocket.RequestCallbackOnPendingRead()); + LogErrorOnFailure(DeviceLayer::SystemLayer.RequestCallbackOnPendingRead(watch->mSocketWatch)); } else { - LogErrorOnFailure(watch->mSocket.ClearCallbackOnPendingRead()); + LogErrorOnFailure(DeviceLayer::SystemLayer.ClearCallbackOnPendingRead(watch->mSocketWatch)); } if (event & AVAHI_WATCH_OUT) { - LogErrorOnFailure(watch->mSocket.RequestCallbackOnPendingWrite()); + LogErrorOnFailure(DeviceLayer::SystemLayer.RequestCallbackOnPendingWrite(watch->mSocketWatch)); } else { - LogErrorOnFailure(watch->mSocket.ClearCallbackOnPendingWrite()); + LogErrorOnFailure(DeviceLayer::SystemLayer.ClearCallbackOnPendingWrite(watch->mSocketWatch)); } } AvahiWatchEvent Poller::WatchGetEvents(AvahiWatch * watch) { - return ToAvahiWatchEvent(watch->mSocket.GetPendingEvents()); + return watch->mPendingIO; } void Poller::WatchFree(AvahiWatch * watch) @@ -214,7 +208,7 @@ void Poller::WatchFree(AvahiWatch * watch) void Poller::WatchFree(AvahiWatch & watch) { - (void) watch.mSocket.ReleaseFD(); + DeviceLayer::SystemLayer.StopWatchingSocket(&watch.mSocketWatch); mWatches.erase(std::remove_if(mWatches.begin(), mWatches.end(), [&watch](const std::unique_ptr & aValue) { return aValue.get() == &watch; }), mWatches.end()); diff --git a/src/platform/Linux/MdnsImpl.h b/src/platform/Linux/MdnsImpl.h index 7360c148b6ed4b..26108905b0bdf5 100644 --- a/src/platform/Linux/MdnsImpl.h +++ b/src/platform/Linux/MdnsImpl.h @@ -34,12 +34,13 @@ #include #include "lib/mdns/platform/Mdns.h" -#include "system/WatchableSocket.h" struct AvahiWatch { - chip::System::WatchableSocket mSocket; + int mSocket; + chip::System::SocketWatchToken mSocketWatch; AvahiWatchCallback mCallback; ///< The function to be called when interested events happened on mFd. + AvahiWatchEvent mPendingIO; ///< The pending events from the currently active or most recent callback. void * mContext; ///< A pointer to application-specific context. void * mPoller; ///< The poller created this watch. }; diff --git a/src/platform/tests/TestMdns.cpp b/src/platform/tests/TestMdns.cpp index 55bdd7f33abc2a..1e625b15dddf4f 100644 --- a/src/platform/tests/TestMdns.cpp +++ b/src/platform/tests/TestMdns.cpp @@ -150,6 +150,7 @@ int TestMdns() retVal = EXIT_FAILURE; } } + t.join(); return retVal; } diff --git a/src/system/BUILD.gn b/src/system/BUILD.gn index fc6c8d2bc9c41c..aecd51a718ed82 100644 --- a/src/system/BUILD.gn +++ b/src/system/BUILD.gn @@ -96,9 +96,6 @@ buildconfig_header("system_buildconfig") { } defines += [ "CHIP_SYSTEM_WATCHABLE_EVENT_MANAGER_CONFIG_FILE=" ] - if (chip_system_config_use_sockets) { - defines += [ "CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE=" ] - } } config("system_config") { @@ -169,9 +166,7 @@ static_library("system") { if (chip_system_config_use_sockets) { sources += [ - "WatchableSocket${chip_system_config_event_loop}.cpp", - "WatchableSocket${chip_system_config_event_loop}.h", - "WatchableSocket.h", + "SocketEvents.h", ] if (chip_system_config_event_loop == "Libevent") { libs = [ "event" ] diff --git a/src/system/SocketEvents.h b/src/system/SocketEvents.h new file mode 100644 index 00000000000000..b0b1c7de0e3e86 --- /dev/null +++ b/src/system/SocketEvents.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Project CHIP Authors + * + * 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 + +namespace chip { +namespace System { + +enum class SocketEventFlags : uint8_t +{ + kRead = 0x1, /**< Bit flag indicating if there is a read event on a socket. */ + kWrite = 0x2, /**< Bit flag indicating if there is a write event on a socket. */ + kExcept = 0x4, /**< Bit flag indicating if there is an exceptional condition on a socket (e.g. out-of-band data). */ + kError = 0x8, /**< Bit flag indicating if there is an error event on a socket. */ +}; + +using SocketEvents = BitFlags; + +using SocketWatchToken = intptr_t; +using SocketWatchCallback = void (*)(SocketEvents events, intptr_t data); + +constexpr int kInvalidFd = -1; + +} // namespace System +} // namespace chip diff --git a/src/system/SystemLayer.cpp b/src/system/SystemLayer.cpp index 83ffc1cefa73e3..442f21bef5ed46 100644 --- a/src/system/SystemLayer.cpp +++ b/src/system/SystemLayer.cpp @@ -30,105 +30,89 @@ namespace chip { namespace System { -Layer::Layer() : mLayerState(kLayerState_NotInitialized) {} +Layer::Layer() : mLayerState(LayerState::kUninitialized) {} CHIP_ERROR Layer::Init() { - VerifyOrReturnError(State() == kLayerState_NotInitialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(State() == LayerState::kUninitialized, CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(mWatchableEventsManager.Init(*this)); - this->mLayerState = kLayerState_Initialized; + this->mLayerState = LayerState::kInitialized; return CHIP_NO_ERROR; } CHIP_ERROR Layer::Shutdown() { - VerifyOrReturnError(State() == kLayerState_Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(mWatchableEventsManager.Shutdown()); - this->mLayerState = kLayerState_NotInitialized; + this->mLayerState = LayerState::kUninitialized; return CHIP_NO_ERROR; } -/** - * @brief - * This method starts a one-shot timer. - * - * @note - * Only a single timer is allowed to be started with the same @a aComplete and @a aAppState - * arguments. If called with @a aComplete and @a aAppState identical to an existing timer, - * the currently-running timer will first be cancelled. - * - * @param[in] aDelayMilliseconds Time in milliseconds before this timer fires. - * @param[in] aComplete A pointer to the function called when timer expires. - * @param[in] aAppState A pointer to the application state object used when timer expires. - * - * @return CHIP_NO_ERROR On success. - * @return CHIP_ERROR_NO_MEMORY If a timer cannot be allocated. - * @return Other Value indicating timer failed to start. - * - */ -CHIP_ERROR Layer::StartTimer(uint32_t aDelayMilliseconds, Timers::OnCompleteFunct aComplete, void * aAppState) +CHIP_ERROR Layer::StartTimer(uint32_t aDelayMilliseconds, TimerCompleteCallback aComplete, void * aAppState) { - VerifyOrReturnError(State() == kLayerState_Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); return mWatchableEventsManager.StartTimer(aDelayMilliseconds, aComplete, aAppState); } -/** - * @brief - * This method cancels a 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] aOnComplete 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 Layer::CancelTimer(Timers::OnCompleteFunct aOnComplete, void * aAppState) +void Layer::CancelTimer(TimerCompleteCallback aOnComplete, void * aAppState) { - VerifyOrReturn(this->State() == kLayerState_Initialized); + VerifyOrReturn(this->State() == LayerState::kInitialized); return mWatchableEventsManager.CancelTimer(aOnComplete, aAppState); } -/** - * @brief - * Schedules a function with a signature identical to - * `OnCompleteFunct` to be run as soon as possible on the CHIP - * thread. - * - * @note - * This function could, in principle, be implemented as - * `StartTimer`. The specification for - * `SystemTimer` however permits certain optimizations that might - * make that implementation impossible. Specifically, `SystemTimer` - * API may only be called from the thread owning the particular - * `SystemLayer`, whereas the `ScheduleWork` may be called from - * any thread. Additionally, whereas the `SystemTimer` API permits - * the invocation of the already expired handler in line, - * `ScheduleWork` guarantees that the handler function will be - * called only after the current CHIP event completes. - * - * @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 CHIP_ERROR_INCORRECT_STATE If the SystemLayer has - * not been initialized. - * - * @retval CHIP_ERROR_NO_MEMORY If the SystemLayer cannot - * allocate a new timer. - * - * @retval CHIP_NO_ERROR On success. - */ -CHIP_ERROR Layer::ScheduleWork(Timers::OnCompleteFunct aComplete, void * aAppState) +CHIP_ERROR Layer::ScheduleWork(TimerCompleteCallback aComplete, void * aAppState) { assertChipStackLockedByCurrentThread(); - VerifyOrReturnError(State() == kLayerState_Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); return mWatchableEventsManager.ScheduleWork(aComplete, aAppState); } +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS + +CHIP_ERROR Layer::StartWatchingSocket(int fd, SocketWatchToken * tokenOut) +{ + return mWatchableEventsManager.StartWatchingSocket(fd, tokenOut); +} + +CHIP_ERROR Layer::SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data) +{ + return mWatchableEventsManager.SetCallback(token, callback, data); +} + +CHIP_ERROR Layer::RequestCallbackOnPendingRead(SocketWatchToken token) +{ + return mWatchableEventsManager.RequestCallbackOnPendingRead(token); +} + +CHIP_ERROR Layer::RequestCallbackOnPendingWrite(SocketWatchToken token) +{ + return mWatchableEventsManager.RequestCallbackOnPendingWrite(token); +} + +CHIP_ERROR Layer::ClearCallbackOnPendingRead(SocketWatchToken token) +{ + VerifyOrReturnError(State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); + return mWatchableEventsManager.ClearCallbackOnPendingRead(token); +} + +CHIP_ERROR Layer::ClearCallbackOnPendingWrite(SocketWatchToken token) +{ + VerifyOrReturnError(State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); + return mWatchableEventsManager.ClearCallbackOnPendingWrite(token); +} + +CHIP_ERROR Layer::StopWatchingSocket(SocketWatchToken * tokenInOut) +{ + VerifyOrReturnError(State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); + return mWatchableEventsManager.StopWatchingSocket(tokenInOut); +} + +SocketWatchToken Layer::InvalidSocketWatchToken() +{ + return mWatchableEventsManager.InvalidSocketWatchToken(); +} + +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS + } // namespace System } // namespace chip diff --git a/src/system/SystemLayer.h b/src/system/SystemLayer.h index 83052343c12673..d3b7d55052ebcc 100644 --- a/src/system/SystemLayer.h +++ b/src/system/SystemLayer.h @@ -38,6 +38,10 @@ #include #include +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS +#include +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS + #if CHIP_SYSTEM_CONFIG_USE_DISPATCH #include #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH @@ -45,8 +49,9 @@ namespace chip { namespace System { +using TimerCompleteCallback = void (*)(Layer * aLayer, void * appState); + class Layer; -class Timer; class Object; class PlatformEventing @@ -63,10 +68,10 @@ class PlatformEventing * * The state of a Layer object. */ -enum LayerState +enum class LayerState { - kLayerState_NotInitialized = 0, /**< Not initialized state. */ - kLayerState_Initialized = 1 /**< Initialized state. */ + kUninitialized = 0, /**< Not initialized state. */ + kInitialized = 1 /**< Initialized state. */ }; /** @@ -85,10 +90,125 @@ class DLL_EXPORT Layer LayerState State() const { return mLayerState; } - CHIP_ERROR StartTimer(uint32_t aMilliseconds, Timers::OnCompleteFunct aComplete, void * aAppState); - void CancelTimer(Timers::OnCompleteFunct aOnComplete, void * aAppState); - CHIP_ERROR ScheduleWork(Timers::OnCompleteFunct aComplete, void * aAppState); - WatchableEventManager & WatchableEventsManager() { return mWatchableEventsManager; } + /** + * @brief + * This method starts a one-shot timer. + * + * @note + * Only a single timer is allowed to be started with the same @a aComplete and @a aAppState + * arguments. If called with @a aComplete and @a aAppState identical to an existing timer, + * the currently-running timer will first be cancelled. + * + * @param[in] aDelayMilliseconds Time in milliseconds before this timer fires. + * @param[in] aComplete A pointer to the function called when timer expires. + * @param[in] aAppState A pointer to the application state object used when timer expires. + * + * @return CHIP_NO_ERROR On success. + * @return CHIP_ERROR_NO_MEMORY If a timer cannot be allocated. + * @return Other Value indicating timer failed to start. + */ + CHIP_ERROR StartTimer(uint32_t aDelayMilliseconds, TimerCompleteCallback aComplete, void * aAppState); + + /** + * @brief + * This method cancels a 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] aOnComplete 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 CancelTimer(TimerCompleteCallback aOnComplete, void * aAppState); + + /** + * @brief + * Schedules a function with a signature identical to `OnCompleteFunct` to be run as soon as possible in the CHIP context. + * + * @note + * This function could, in principle, be implemented as `StartTimer`. The specification for `SystemTimer` however + * permits certain optimizations that might make that implementation impossible. Specifically, `SystemTimer` + * API may only be called from the thread owning the particular `SystemLayer`, whereas the `ScheduleWork` may be + * called from any thread. Additionally, whereas the `SystemTimer` API permits the invocation of the already + * expired handler in line, `ScheduleWork` guarantees that the handler function will be called only after the + * current CHIP event completes. + * + * @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 CHIP_ERROR_INCORRECT_STATE If the SystemLayer has + * not been initialized. + * + * @retval CHIP_ERROR_NO_MEMORY If the SystemLayer cannot + * allocate a new timer. + * + * @retval CHIP_NO_ERROR On success. + */ + CHIP_ERROR ScheduleWork(TimerCompleteCallback aComplete, void * aAppState); + +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS + + /** + * Initialize watching for events on a file descriptor. + * + * Returns an opaque token through @a tokenOut that must be passed to subsequent operations for this file descriptor. + * StopWatchingSocket() must be called before closing the file descriptor. + */ + CHIP_ERROR StartWatchingSocket(int fd, SocketWatchToken * tokenOut); + + /** + * Register a callback function. + * + * The callback will be invoked (with the CHIP stack lock held) when requested event(s) are ready. + */ + CHIP_ERROR SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data); + + /** + * Request a callback when the associated file descriptor is readable. + */ + CHIP_ERROR RequestCallbackOnPendingRead(SocketWatchToken token); + + /** + * Request a callback when the associated file descriptor is writable. + */ + CHIP_ERROR RequestCallbackOnPendingWrite(SocketWatchToken token); + + /** + * Cancel a request for a callback when the associated file descriptor is readable. + */ + CHIP_ERROR ClearCallbackOnPendingRead(SocketWatchToken token); + + /** + * Cancel a request for a callback when the associated file descriptor is writable. + */ + CHIP_ERROR ClearCallbackOnPendingWrite(SocketWatchToken token); + + /** + * Stop watching for events on the associated file descriptor. + * + * This MUST be called before the file descriptor is closed. + * It is not necessary to clear callback requests before calling this function. + */ + CHIP_ERROR StopWatchingSocket(SocketWatchToken * tokenInOut); + + /** + * Return a SocketWatchToken that is guaranteed not to be valid. Clients may use this to initialize variables. + */ + SocketWatchToken InvalidSocketWatchToken(); + +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS + + WatchableEventManager & + WatchableEventsManager() + { + return mWatchableEventsManager; + } Clock & GetClock() { return mClock; } diff --git a/src/system/SystemStats.cpp b/src/system/SystemStats.cpp index 9ab4e562e52423..d03db12172d1bd 100644 --- a/src/system/SystemStats.cpp +++ b/src/system/SystemStats.cpp @@ -87,8 +87,10 @@ void UpdateSnapshot(Snapshot & aSnapshot) memcpy(&aSnapshot.mResourcesInUse, &sResourcesInUse, sizeof(aSnapshot.mResourcesInUse)); memcpy(&aSnapshot.mHighWatermarks, &sHighWatermarks, sizeof(aSnapshot.mHighWatermarks)); +#if CHIP_SYSTEM_CONFIG_USE_TIMER_POOL chip::System::Timer::GetStatistics(aSnapshot.mResourcesInUse[kSystemLayer_NumTimers], aSnapshot.mHighWatermarks[kSystemLayer_NumTimers]); +#endif // CHIP_SYSTEM_CONFIG_USE_TIMER_POOL SYSTEM_STATS_UPDATE_LWIP_PBUF_COUNTS(); } diff --git a/src/system/SystemTimer.cpp b/src/system/SystemTimer.cpp index 88f8a14351a307..fa30cceae9767a 100644 --- a/src/system/SystemTimer.cpp +++ b/src/system/SystemTimer.cpp @@ -79,7 +79,7 @@ namespace System { ObjectPool Timer::sPool; -Timer * Timer::New(System::Layer & systemLayer, uint32_t delayMilliseconds, Timers::OnCompleteFunct onComplete, void * appState) +Timer * Timer::New(System::Layer & systemLayer, uint32_t delayMilliseconds, TimerCompleteCallback onComplete, void * appState) { Timer * timer = Timer::sPool.TryCreate(systemLayer); if (timer == nullptr) @@ -100,7 +100,7 @@ Timer * Timer::New(System::Layer & systemLayer, uint32_t delayMilliseconds, Time void Timer::Clear() { - Timers::OnCompleteFunct lOnComplete = this->mOnComplete; + TimerCompleteCallback lOnComplete = this->mOnComplete; // Check if the timer is armed VerifyOrReturn(lOnComplete != nullptr); @@ -112,14 +112,11 @@ void Timer::Clear() AppState = nullptr; } -/** - * This method is called by the underlying timer mechanism provided by the platform when the timer fires. - */ void Timer::HandleComplete() { // Save information needed to perform the callback. Layer & lLayer = this->SystemLayer(); - const Timers::OnCompleteFunct lOnComplete = this->mOnComplete; + const TimerCompleteCallback lOnComplete = this->mOnComplete; void * lAppState = this->AppState; // Check if timer is armed @@ -191,7 +188,7 @@ Timer * Timer::List::Remove(Timer * remove) return mHead; } -Timer * Timer::List::Remove(Timers::OnCompleteFunct aOnComplete, void * aAppState) +Timer * Timer::List::Remove(TimerCompleteCallback aOnComplete, void * aAppState) { Timer * previous = nullptr; for (Timer * timer = mHead; timer != nullptr; timer = timer->mNextTimer) diff --git a/src/system/SystemTimer.h b/src/system/SystemTimer.h index d897ad1251155a..fd8c20c5a93fd8 100644 --- a/src/system/SystemTimer.h +++ b/src/system/SystemTimer.h @@ -50,11 +50,7 @@ namespace chip { namespace System { -namespace Timers { - -typedef void (*OnCompleteFunct)(Layer * aLayer, void * appState); - -} // namespace Timers +using TimerCompleteCallback = void (*)(Layer * aLayer, void * appState); #if CHIP_SYSTEM_CONFIG_USE_TIMER_POOL @@ -64,18 +60,64 @@ typedef void (*OnCompleteFunct)(Layer * aLayer, void * appState); class DLL_EXPORT Timer : public Object { public: + /** + * List of timers ordered by completion time. + * + * @note + * This is an intrusive linked list, using the Timer field `mNextTimer`. + */ class List { public: List() : mHead(nullptr) {} List(Timer * head) : mHead(head) {} - bool Empty() const { return mHead == nullptr; } + + /** + * Add a timer to the list + * + * @return The new earliest timer in the list. If this is the newly added timer, that implies it is earlier + * than any existing timer. + */ Timer * Add(Timer * add); + + /** + * Remove the given timer from the list, if present. It is not an error for the timer not to be present. + * + * @return The new earliest timer in the list, or nullptr if the list is empty. + */ Timer * Remove(Timer * remove); - Timer * Remove(Timers::OnCompleteFunct onComplete, void * appState); + + /** + * Remove the first timer with the given properties, if present. It is not an error for no such timer to be present. + * + * @return The removed timer, or nullptr if the list contains no matching timer. + */ + Timer * Remove(TimerCompleteCallback onComplete, void * appState); + + /** + * Remove and return the earliest timer in the list. + * + * @return The earliest timer, or nullptr if the list is empty. + */ Timer * PopEarliest(); + + /** + * Remove and return the earliest timer in the list, provided it expires earlier than the given time @a t. + * + * @return The earliest timer expiring before @a t, or nullptr if there is no such timer. + */ Timer * PopIfEarlier(Clock::MonotonicMilliseconds t); + + /** + * Remove and return all timers that expire before the given time @a t. + * + * @return An ordered linked list (by `mNextTimer`) of all timers that expire before @a t, or nullptr if there are none. + */ Timer * ExtractEarlier(Clock::MonotonicMilliseconds t); + + /** + * Get the earliest timer in the list. + */ Timer * Earliest() const { return mHead; } protected: @@ -83,6 +125,11 @@ class DLL_EXPORT Timer : public Object List(const List &) = delete; List & operator=(const List &) = delete; }; + /** + * List of timers ordered by completion time. + * + * This extends Timer::List to lock all access to the list. + */ class MutexedList : private List { public: @@ -103,7 +150,7 @@ class DLL_EXPORT Timer : public Object std::lock_guard lock(mMutex); return List::Remove(remove); } - Timer * Remove(Timers::OnCompleteFunct onComplete, void * appState) + Timer * Remove(TimerCompleteCallback onComplete, void * appState) { std::lock_guard lock(mMutex); return List::Remove(onComplete, appState); @@ -135,10 +182,37 @@ class DLL_EXPORT Timer : public Object MutexedList & operator=(const MutexedList &) = delete; }; - static Timer * New(System::Layer & systemLayer, uint32_t delayMilliseconds, Timers::OnCompleteFunct onComplete, + /** + * Obtain a new timer from the system object pool. + */ + static Timer * New(System::Layer & systemLayer, uint32_t delayMilliseconds, TimerCompleteCallback onComplete, void * appState); + + /** + * Return the expiration time. + */ + Clock::MonotonicMilliseconds AwakenTime() const { return mAwakenTime; } + + /** + * Fire the timer. + * + * This method is called by the underlying timer mechanism provided by the platform when the timer fires. + * It invalidates this timer object, calls Object::Release() on it, and invokes the callback. + */ + void HandleComplete(); + + /** + * Invalidate the timer fields. This is intended for timer cancellation, and typically this will be followed by + * an object Release(). + * + * @note + * The Timer owner is responsible for ensuring this timer is not in use, e.g. in a List or by a platform timer implementation. + */ void Clear(); + /** + * Read timer pool statistics. + */ static void GetStatistics(chip::System::Stats::count_t & aNumInUse, chip::System::Stats::count_t & aHighWatermark) { sPool.GetStatistics(aNumInUse, aHighWatermark); @@ -146,12 +220,9 @@ class DLL_EXPORT Timer : public Object private: friend class WatchableEventManager; - static ObjectPool sPool; - void HandleComplete(); - - Timers::OnCompleteFunct mOnComplete; + TimerCompleteCallback mOnComplete; Clock::MonotonicMilliseconds mAwakenTime; Timer * mNextTimer; diff --git a/src/system/WakeEvent.cpp b/src/system/WakeEvent.cpp index d9b9ca9e370e19..0b913ef1863f04 100644 --- a/src/system/WakeEvent.cpp +++ b/src/system/WakeEvent.cpp @@ -30,6 +30,7 @@ // Include additional CHIP headers #include #include +#include // Include system and language headers #include @@ -53,7 +54,7 @@ inline int SetNonBlockingMode(int fd) } } // anonymous namespace -CHIP_ERROR WakeEvent::Open(WatchableEventManager & watchState) +CHIP_ERROR WakeEvent::Open(Layer & systemLayer) { enum { @@ -71,20 +72,22 @@ CHIP_ERROR WakeEvent::Open(WatchableEventManager & watchState) if (SetNonBlockingMode(fds[FD_WRITE]) < 0) return chip::System::MapErrorPOSIX(errno); + mReadFD = fds[FD_READ]; mWriteFD = fds[FD_WRITE]; - mFD.Init(watchState); - ReturnErrorOnFailure(mFD.Attach(fds[FD_READ])); - mFD.SetCallback(Confirm, reinterpret_cast(this)); - ReturnErrorOnFailure(mFD.RequestCallbackOnPendingRead()); + ReturnErrorOnFailure(systemLayer.StartWatchingSocket(mReadFD, &mReadWatch)); + ReturnErrorOnFailure(systemLayer.SetCallback(mReadWatch, Confirm, reinterpret_cast(this))); + ReturnErrorOnFailure(systemLayer.RequestCallbackOnPendingRead(mReadWatch)); return CHIP_NO_ERROR; } -void WakeEvent::Close() +void WakeEvent::Close(Layer & systemLayer) { - mFD.Close(); + systemLayer.StopWatchingSocket(&mReadWatch); + VerifyOrDie(::close(mReadFD) == 0); VerifyOrDie(::close(mWriteFD) == 0); + mReadFD = -1; mWriteFD = -1; } @@ -95,7 +98,7 @@ void WakeEvent::Confirm() do { - res = ::read(mFD.GetFD(), buffer, sizeof(buffer)); + res = ::read(mReadFD, buffer, sizeof(buffer)); if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { ChipLogError(chipSystemLayer, "System wake event confirm failed: %s", ErrorStr(chip::System::MapErrorPOSIX(errno))); @@ -118,33 +121,33 @@ CHIP_ERROR WakeEvent::Notify() #else // CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE -CHIP_ERROR WakeEvent::Open(WatchableEventManager & watchState) +CHIP_ERROR WakeEvent::Open(Layer & systemLayer) { - mFD.Init(watchState); - - const int fd = ::eventfd(0, 0); - if (fd == -1) + mReadFD = ::eventfd(0, 0); + if (mReadFD == -1) { return chip::System::MapErrorPOSIX(errno); } - mFD.Attach(fd); - mFD.SetCallback(Confirm, reinterpret_cast(this)); - mFD.RequestCallbackOnPendingRead(); + ReturnErrorOnFailure(systemLayer.StartWatchingSocket(mReadFD, &mReadWatch)); + ReturnErrorOnFailure(systemLayer.SetCallback(mReadWatch, Confirm, reinterpret_cast(this))); + ReturnErrorOnFailure(systemLayer.RequestCallbackOnPendingRead(mReadWatch)); return CHIP_NO_ERROR; } -void WakeEvent::Close() +void WakeEvent::Close(Layer & systemLayer) { - mFD.Close(); + systemLayer.StopWatchingSocket(&mReadWatch); + VerifyOrDie(::close(mReadFD) == 0); + mReadFD = -1; } void WakeEvent::Confirm() { uint64_t value; - if (::read(mFD.GetFD(), &value, sizeof(value)) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) + if (::read(mReadFD, &value, sizeof(value)) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { ChipLogError(chipSystemLayer, "System wake event confirm failed: %s", ErrorStr(chip::System::MapErrorPOSIX(errno))); } @@ -154,7 +157,7 @@ CHIP_ERROR WakeEvent::Notify() { uint64_t value = 1; - if (::write(mFD.GetFD(), &value, sizeof(value)) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) + if (::write(mReadFD, &value, sizeof(value)) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { return chip::System::MapErrorPOSIX(errno); } diff --git a/src/system/WakeEvent.h b/src/system/WakeEvent.h index 727a64d80124a2..9d0323ca9edeb0 100644 --- a/src/system/WakeEvent.h +++ b/src/system/WakeEvent.h @@ -28,13 +28,13 @@ #if CHIP_SYSTEM_CONFIG_USE_SOCKETS #include -#include +#include namespace chip { namespace System { +class Layer; class WakeEventTest; -class WatchableEventManager; /** * @class WakeEvent @@ -45,8 +45,8 @@ class WatchableEventManager; class WakeEvent { public: - CHIP_ERROR Open(WatchableEventManager & watchState); /**< Initialize the pipeline */ - void Close(); /**< Close both ends of the pipeline. */ + CHIP_ERROR Open(Layer & systemLayer); /**< Initialize the pipeline */ + void Close(Layer & systemLayer); /**< Close both ends of the pipeline. */ CHIP_ERROR Notify(); /**< Set the event. */ void Confirm(); /**< Clear the event. */ @@ -54,13 +54,14 @@ class WakeEvent private: friend class WakeEventTest; - int GetReadFD() const { return mFD.GetFD(); } - static void Confirm(WatchableSocket & socket) { reinterpret_cast(socket.GetCallbackData())->Confirm(); } + int GetReadFD() const { return mReadFD; } + static void Confirm(System::SocketEvents events, intptr_t data) { reinterpret_cast(data)->Confirm(); } #if CHIP_SYSTEM_CONFIG_USE_POSIX_PIPE int mWriteFD; #endif - WatchableSocket mFD; + int mReadFD; + SocketWatchToken mReadWatch; }; } // namespace System diff --git a/src/system/WatchableEventManager.h b/src/system/WatchableEventManager.h index 7385480ab0880f..cf4f17b9853e4d 100644 --- a/src/system/WatchableEventManager.h +++ b/src/system/WatchableEventManager.h @@ -57,7 +57,7 @@ class WatchableEventManager; */ /** - * @fn CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, Timers::OnCompleteFunct onComplete, void * + * @fn CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, TimerCompleteCallback onComplete, void * * appState) * * This method starts a one-shot timer. @@ -76,7 +76,7 @@ class WatchableEventManager; */ /** - * @fn void WatchableEventManager::CancelTimer(Timers::OnCompleteFunct onComplete, void * appState) + * @fn void WatchableEventManager::CancelTimer(TimerCompleteCallback onComplete, void * appState) * * This method cancels a one-shot timer, started earlier through @p StartTimer(). * @@ -89,7 +89,7 @@ class WatchableEventManager; */ /** - * @fn CHIP_ERROR WatchableEventManager::ScheduleWork(Timers::OnCompleteFunct onComplete, void * appState) + * @fn CHIP_ERROR WatchableEventManager::ScheduleWork(TimerCompleteCallback onComplete, void * appState) * * Schedules a function to be run as soon as possible on the CHIP thread. * diff --git a/src/system/WatchableEventManagerLibevent.cpp b/src/system/WatchableEventManagerLibevent.cpp index bf79e75ad08c19..64a60c79e7bff4 100644 --- a/src/system/WatchableEventManagerLibevent.cpp +++ b/src/system/WatchableEventManagerLibevent.cpp @@ -25,7 +25,10 @@ #include #include #include -#include + +#include +#include +#include #if CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ @@ -59,8 +62,6 @@ System::SocketEvents SocketEventsFromLibeventFlags(short eventFlags) .Set(SocketEventFlags::kWrite, eventFlags & EV_WRITE); } -void TimeoutCallbackHandler(evutil_socket_t fd, short eventFlags, void * data) {} - } // anonymous namespace CHIP_ERROR WatchableEventManager::Init(System::Layer & systemLayer) @@ -76,96 +77,67 @@ CHIP_ERROR WatchableEventManager::Init(System::Layer & systemLayer) } #endif // CHIP_CONFIG_LIBEVENT_DEBUG_CHECKS - mEventBase = event_base_new(); - mTimeoutEvent = evtimer_new(mEventBase, TimeoutCallbackHandler, event_self_cbarg()); - mActiveSockets = nullptr; mSystemLayer = &systemLayer; + mEventBase = event_base_new(); + VerifyOrReturnError(mEventBase != nullptr, CHIP_ERROR_NO_MEMORY); + +#if CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ + mMdnsTimeoutEvent = evtimer_new(mEventBase, MdnsTimeoutCallbackHandler, this); + VerifyOrReturnError(mMdnsTimeoutEvent != nullptr, CHIP_ERROR_NO_MEMORY); +#endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING mHandleSelectThread = PTHREAD_NULL; #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING - return mTimerList.Init(); -} - -void WatchableEventManager::PrepareEvents() -{ - const Clock::MonotonicMilliseconds currentTime = Clock::GetMonotonicMilliseconds(); - Clock::MonotonicMilliseconds awakenTime = currentTime; - - Timer * timer = mTimerList.Earliest(); - if (timer && Clock::IsEarlier(timer->mAwakenTime, awakenTime)) - { - awakenTime = timer->mAwakenTime; - } - - const Clock::MonotonicMilliseconds sleepTime = (awakenTime > currentTime) ? (awakenTime - currentTime) : 0; - timeval nextTimeout; - MillisecondsToTimeval(sleepTime, nextTimeout); - -#if CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ && !__MBED__ - chip::Mdns::GetMdnsTimeout(nextTimeout); -#endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ + Mutex::Init(mTimerListMutex); - if (nextTimeout.tv_sec || nextTimeout.tv_usec) - { - evtimer_add(mTimeoutEvent, &nextTimeout); - } + return CHIP_NO_ERROR; } -void WatchableEventManager::WaitForEvents() -{ - VerifyOrDie(mEventBase != nullptr); - event_base_loop(mEventBase, EVLOOP_ONCE); +#if CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ + +// static +void WatchableEventManager::MdnsTimeoutCallbackHandler(evutil_socket_t fd, short eventFlags, void * data) { + reinterpret_cast(data)->MdnsTimeoutCallbackHandler(); } -void WatchableEventManager::HandleEvents() +void WatchableEventManager::MdnsTimeoutCallbackHandler() { #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING mHandleSelectThread = pthread_self(); #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING - // Obtain the list of currently expired timers. Any new timers added by timer callback are NOT handled on this pass, - // since that could result in infinite handling of new timers blocking any other progress. - Timer::List expiredTimers(mTimerList.ExtractEarlier(1 + Clock::GetMonotonicMilliseconds())); - Timer * timer = nullptr; - while ((timer = expiredTimers.PopEarliest()) != nullptr) - { - timer->HandleComplete(); - } - -#if CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ chip::Mdns::HandleMdnsTimeout(); -#endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ - - while (mActiveSockets != nullptr) - { - WatchableSocket * const watcher = mActiveSockets; - mActiveSockets = watcher->mActiveNext; - watcher->InvokeCallback(); - } #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING mHandleSelectThread = PTHREAD_NULL; #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING } +#endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ CHIP_ERROR WatchableEventManager::Shutdown() { event_base_loopbreak(mEventBase); - event_free(mTimeoutEvent); - mTimeoutEvent = nullptr; - event_base_free(mEventBase); - mEventBase = nullptr; - Timer * timer; - while ((timer = mTimerList.PopEarliest()) != nullptr) +#if CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ + if (mMdnsTimeoutEvent != nullptr) { - timer->Clear(); - timer->Release(); + event_free(mMdnsTimeoutEvent); + mMdnsTimeoutEvent = nullptr; } +#endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ + + mTimerListMutex.Lock(); + mTimers.clear(); + mTimerListMutex.Unlock(); + mSocketWatches.clear(); + + event_base_free(mEventBase); + mEventBase = nullptr; mSystemLayer = nullptr; + return CHIP_NO_ERROR; } @@ -195,73 +167,247 @@ void WatchableEventManager::Signal() } } -CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, Timers::OnCompleteFunct onComplete, void * appState) +CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, TimerCompleteCallback onComplete, void * appState) +{ + std::lock_guard lock(mTimerListMutex); + mTimers.push_back(std::make_unique(this, onComplete, appState)); + LibeventTimer * timer = mTimers.back().get(); + if (timer == nullptr) + { + mTimers.pop_back(); + return CHIP_ERROR_NO_MEMORY; + } + + event * e = evtimer_new(mEventBase, TimerCallbackHandler, timer); + VerifyOrReturnError(e != nullptr, CHIP_ERROR_NO_MEMORY); + timer->mEvent = e; + + timeval delay; + MillisecondsToTimeval(delayMilliseconds, delay); + int status = evtimer_add(e, &delay); + VerifyOrReturnError(status == 0, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +void WatchableEventManager::CancelTimer(TimerCompleteCallback onComplete, void * appState) { - // Note: the libevent implementation currently uses a single libevent timer, playing the same role as the select() timeout. - // A more ‘native' implementation would have Timer contain a libevent timer and callback data for each CHIP timer. - CHIP_SYSTEM_FAULT_INJECT(FaultInjection::kFault_TimeoutImmediate, delayMilliseconds = 0); + std::lock_guard lock(mTimerListMutex); + auto it = std::find_if(mTimers.begin(), mTimers.end(), [onComplete, appState](const std::unique_ptr & timer) { + return timer->mOnComplete == onComplete && timer->mCallbackData == appState; + }); + if (it != mTimers.end()) + { + LibeventTimer *timer = it->get(); + mActiveTimers.remove(timer); + mTimers.remove_if([timer](const std::unique_ptr & t) { return t.get() == timer; }); + } +} - CancelTimer(onComplete, appState); +//static +void WatchableEventManager::TimerCallbackHandler(evutil_socket_t fd, short eventFlags, void * data) { + // Copy the necessary timer information and remove it from the list. + LibeventTimer * timer = reinterpret_cast(data); + Layer * systemLayer = timer->mEventManager->mSystemLayer; + TimerCompleteCallback onComplete = timer->mOnComplete; + void *callbackData = timer->mCallbackData; + systemLayer->CancelTimer(onComplete, callbackData); + if (onComplete) + { + onComplete(systemLayer, callbackData); + } +} - Timer * timer = Timer::New(*mSystemLayer, delayMilliseconds, onComplete, appState); - VerifyOrReturnError(timer != nullptr, CHIP_ERROR_NO_MEMORY); +WatchableEventManager::LibeventTimer::~LibeventTimer() +{ + mEventManager = nullptr; + mOnComplete = nullptr; + mCallbackData = nullptr; + if (mEvent) + { + if (evtimer_pending(mEvent, nullptr)) + { + event_del(mEvent); + } + event_free(mEvent); + mEvent = nullptr; + } +}; - if (mTimerList.Add(timer) == timer) +CHIP_ERROR WatchableEventManager::StartWatchingSocket(int fd, SocketWatchToken * tokenOut) +{ + mSocketWatches.push_back(std::make_unique(this, fd)); + SocketWatch * watch = mSocketWatches.back().get(); + if (watch == nullptr) { - // The new timer is the earliest, so the time until the next event has probably changed. - Signal(); + mSocketWatches.pop_back(); + return CHIP_ERROR_NO_MEMORY; } + + *tokenOut = reinterpret_cast(watch); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WatchableEventManager::SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data) +{ + SocketWatch * watch = reinterpret_cast(token); + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + watch->mCallback = callback; + watch->mCallbackData = data; + return CHIP_NO_ERROR; +} + +CHIP_ERROR WatchableEventManager::RequestCallbackOnPendingRead(SocketWatchToken token) +{ + return SetWatch(token, EV_READ); +} + +CHIP_ERROR WatchableEventManager::RequestCallbackOnPendingWrite(SocketWatchToken token) +{ + return SetWatch(token, EV_WRITE); +} + +CHIP_ERROR WatchableEventManager::ClearCallbackOnPendingRead(SocketWatchToken token) +{ + return ClearWatch(token, EV_READ); +} + +CHIP_ERROR WatchableEventManager::ClearCallbackOnPendingWrite(SocketWatchToken token) +{ + return ClearWatch(token, EV_WRITE); +} + +CHIP_ERROR WatchableEventManager::StopWatchingSocket(SocketWatchToken * tokenInOut) +{ + SocketWatch * watch = reinterpret_cast(*tokenInOut); + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + *tokenInOut = InvalidSocketWatchToken(); + + mActiveSocketWatches.remove(watch); + mSocketWatches.remove_if([watch](const std::unique_ptr & w) { return w.get() == watch; }); return CHIP_NO_ERROR; } -void WatchableEventManager::CancelTimer(Timers::OnCompleteFunct onComplete, void * appState) +SocketWatchToken InvalidSocketWatchToken() { return reinterpret_cast(nullptr); } + +CHIP_ERROR WatchableEventManager::SetWatch(SocketWatchToken token, short eventFlags) { - Timer * timer = mTimerList.Remove(onComplete, appState); - VerifyOrReturn(timer != nullptr); + SocketWatch * watch = reinterpret_cast(token); + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - timer->Clear(); - timer->Release(); - Signal(); + const short oldFlags = watch->mEvent ? event_get_events(watch->mEvent) : 0; + return UpdateWatch(watch, static_cast(EV_PERSIST | oldFlags | eventFlags)); +} + +CHIP_ERROR WatchableEventManager::ClearWatch(SocketWatchToken token, short eventFlags) +{ + SocketWatch * watch = reinterpret_cast(token); + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + const short oldFlags = watch->mEvent ? event_get_events(watch->mEvent) : 0; + return UpdateWatch(watch, static_cast(EV_PERSIST | (oldFlags & ~eventFlags))); +} + +CHIP_ERROR WatchableEventManager::UpdateWatch(SocketWatch *watch, short eventFlags) +{ + if (watch->mEvent != nullptr) + { + if (event_get_events(watch->mEvent) == eventFlags) + { + // No update needed. + return CHIP_NO_ERROR; + } + if (event_pending(watch->mEvent, EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL, nullptr)) + { + event_del(watch->mEvent); + } + event_free(watch->mEvent); + watch->mEvent = nullptr; + } + + if (eventFlags) + { + // libevent requires the socket to already be non-blocking. + int flags = ::fcntl(watch->mFD, F_GETFL, 0); + if ((flags & O_NONBLOCK) == 0) + { + int status = ::fcntl(watch->mFD, F_SETFL, flags | O_NONBLOCK); + VerifyOrReturnError(status == 0, chip::System::MapErrorPOSIX(errno)); + } + watch->mEvent = event_new(mEventBase, watch->mFD, eventFlags, SocketCallbackHandler, watch); + VerifyOrReturnError(watch->mEvent != nullptr, CHIP_ERROR_NO_MEMORY); + int status = event_add(watch->mEvent, nullptr); + VerifyOrReturnError(status == 0, CHIP_ERROR_INTERNAL); + } + + return CHIP_NO_ERROR; } // static -void WatchableEventManager::LibeventCallbackHandler(evutil_socket_t fd, short eventFlags, void * data) +void WatchableEventManager::SocketCallbackHandler(evutil_socket_t fd, short eventFlags, void * data) { - WatchableSocket * const watcher = reinterpret_cast(data); - VerifyOrDie(watcher != nullptr); - VerifyOrDie(watcher->mFD == fd); + SocketWatch * const watch = reinterpret_cast(data); + VerifyOrDie(watch != nullptr); + VerifyOrDie(watch->mFD == fd); - watcher->mPendingIO = SocketEventsFromLibeventFlags(eventFlags); + watch->mPendingIO = SocketEventsFromLibeventFlags(eventFlags); + watch->mEventManager->mActiveSocketWatches.push_back(watch); +} - // Add to active list. - WatchableSocket ** pp = &watcher->mSharedState->mActiveSockets; - while (*pp != nullptr) +WatchableEventManager::SocketWatch::~SocketWatch() { + mEventManager = nullptr; + mFD = kInvalidFd; + mCallback = nullptr; + mCallbackData = 0; + if (mEvent) { - if (*pp == watcher) + if (event_pending(mEvent, EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL, nullptr)) { - return; + event_del(mEvent); } - pp = &(*pp)->mActiveNext; + event_free(mEvent); + mEvent = nullptr; } - *pp = watcher; - watcher->mActiveNext = nullptr; } -void WatchableEventManager::RemoveFromQueueIfPresent(WatchableSocket * watcher) +void WatchableEventManager::PrepareEvents() { - VerifyOrDie(watcher != nullptr); - VerifyOrDie(watcher->mSharedState == this); +#if CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ && !__MBED__ + timeval mdnsTimeout = { 0, 0 }; + chip::Mdns::GetMdnsTimeout(mdnsTimeout); + if (mdnsTimeout.tv_sec || mdnsTimeout.tv_usec) + { + evtimer_add(mMdnsTimeoutEvent, &mdnsTimeout); + } +#endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ +} - WatchableSocket ** pp = &mActiveSockets; - while (*pp != nullptr) +void WatchableEventManager::WaitForEvents() +{ + VerifyOrDie(mEventBase != nullptr); + event_base_loop(mEventBase, EVLOOP_ONCE); +} + +void WatchableEventManager::HandleEvents() +{ +#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING + mHandleSelectThread = pthread_self(); +#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING + + while (!mActiveSocketWatches.empty()) { - if (*pp == watcher) + SocketWatch * const watch = mActiveSocketWatches.front(); + mActiveSocketWatches.pop_front(); + if (watch->mPendingIO.HasAny() && watch->mCallback != nullptr) { - *pp = watcher->mActiveNext; - return; + watch->mCallback(watch->mPendingIO, watch->mCallbackData); } - pp = &(*pp)->mActiveNext; } + +#if CHIP_SYSTEM_CONFIG_POSIX_LOCKING + mHandleSelectThread = PTHREAD_NULL; +#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING } } // namespace System diff --git a/src/system/WatchableEventManagerLibevent.h b/src/system/WatchableEventManagerLibevent.h index 634162282559c2..aba46960c795cd 100644 --- a/src/system/WatchableEventManagerLibevent.h +++ b/src/system/WatchableEventManagerLibevent.h @@ -30,6 +30,9 @@ #include #include +#include +#include +#include #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING #include @@ -43,7 +46,7 @@ namespace System { class WatchableEventManager { public: - WatchableEventManager() : mActiveSockets(nullptr), mSystemLayer(nullptr), mEventBase(nullptr), mTimeoutEvent(nullptr) {} + WatchableEventManager() : mSystemLayer(nullptr), mEventBase(nullptr), mMdnsTimeoutEvent(nullptr) {} // Core ‘overrides’. CHIP_ERROR Init(Layer & systemLayer); @@ -51,10 +54,21 @@ class WatchableEventManager void Signal(); // Timer ‘overrides’. - CHIP_ERROR StartTimer(uint32_t delayMilliseconds, Timers::OnCompleteFunct onComplete, void * appState); - void CancelTimer(Timers::OnCompleteFunct onComplete, void * appState); - CHIP_ERROR ScheduleWork(Timers::OnCompleteFunct onComplete, void * appState) { return StartTimer(0, onComplete, appState); } - + CHIP_ERROR StartTimer(uint32_t delayMilliseconds, TimerCompleteCallback onComplete, void * appState); + void CancelTimer(TimerCompleteCallback onComplete, void * appState); + CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState) { return StartTimer(0, onComplete, appState); } + + // Socket watch ‘overrides’. + CHIP_ERROR StartWatchingSocket(int fd, SocketWatchToken * tokenOut); + CHIP_ERROR SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data); + CHIP_ERROR RequestCallbackOnPendingRead(SocketWatchToken token); + CHIP_ERROR RequestCallbackOnPendingWrite(SocketWatchToken token); + CHIP_ERROR ClearCallbackOnPendingRead(SocketWatchToken token); + CHIP_ERROR ClearCallbackOnPendingWrite(SocketWatchToken token); + CHIP_ERROR StopWatchingSocket(SocketWatchToken * tokenInOut); + SocketWatchToken InvalidSocketWatchToken() { return reinterpret_cast(nullptr); } + + // Platform implementation. void EventLoopBegins() {} void PrepareEvents(); void WaitForEvents(); @@ -63,27 +77,62 @@ class WatchableEventManager private: /* - * In this implementation, libevent invokes LibeventCallbackHandler from beneath WaitForEvents(), - * which means that the CHIP stack is unlocked. LibeventCallbackHandler adds the WatchableSocket - * to a queue (implemented as a simple intrusive list to avoid dynamic memory allocation), and - * then HandleEvents() invokes the WatchableSocket callbacks. + * In this implementation, libevent invokes TimerCallbackHandler and SocketCallbackHandler from beneath WaitForEvents(), + * which means that the CHIP stack is unlocked. These handles add the LibeventTimer or SocketWatch respectively to a list, + * then HandleEvents() invokes the client callbacks. */ - friend class WatchableSocket; - static void LibeventCallbackHandler(evutil_socket_t fd, short eventFlags, void * data); - void RemoveFromQueueIfPresent(WatchableSocket * watcher); - - WatchableSocket * mActiveSockets; ///< List of sockets activated by libevent. + struct LibeventTimer + { + LibeventTimer(WatchableEventManager * layer, TimerCompleteCallback onComplete, void * data) : + mEventManager(layer), mOnComplete(onComplete), mCallbackData(data), mEvent(nullptr) + {} + ~LibeventTimer(); + WatchableEventManager * mEventManager; + TimerCompleteCallback mOnComplete; + void * mCallbackData; + event * mEvent; + }; + static void TimerCallbackHandler(evutil_socket_t fd, short eventFlags, void * data); + + struct SocketWatch + { + SocketWatch(WatchableEventManager * layer, int fd) : + mEventManager(layer), mFD(fd), mCallback(nullptr), mCallbackData(0), mEvent(nullptr) + {} + ~SocketWatch(); + WatchableEventManager * mEventManager; + int mFD; + SocketEvents mPendingIO; + SocketWatchCallback mCallback; + intptr_t mCallbackData; + event * mEvent; + }; + CHIP_ERROR SetWatch(SocketWatchToken token, short eventFlags); + CHIP_ERROR ClearWatch(SocketWatchToken token, short eventFlags); + CHIP_ERROR UpdateWatch(SocketWatch * watch, short eventFlags); + static void SocketCallbackHandler(evutil_socket_t fd, short eventFlags, void * data); Layer * mSystemLayer; event_base * mEventBase; ///< libevent shared state. - event * mTimeoutEvent; - Timer::MutexedList mTimerList; + std::list> mTimers; + std::list mActiveTimers; + Mutex mTimerListMutex; + + std::list> mSocketWatches; + std::list mActiveSocketWatches; + WakeEvent mWakeEvent; #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING std::atomic mHandleSelectThread; #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING + +#if CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ + static void MdnsTimeoutCallbackHandler(evutil_socket_t fd, short eventFlags, void * data); + void MdnsTimeoutCallbackHandler(); +#endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ + event * mMdnsTimeoutEvent; }; } // namespace System diff --git a/src/system/WatchableEventManagerLwIP.cpp b/src/system/WatchableEventManagerLwIP.cpp index 0b3b64dc76d086..b68241dd7068ac 100644 --- a/src/system/WatchableEventManagerLwIP.cpp +++ b/src/system/WatchableEventManagerLwIP.cpp @@ -54,7 +54,7 @@ CHIP_ERROR WatchableEventManager::Shutdown() void WatchableEventManager::Signal() {} -CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, Timers::OnCompleteFunct onComplete, void * appState) +CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, TimerCompleteCallback onComplete, void * appState) { CHIP_SYSTEM_FAULT_INJECT(FaultInjection::kFault_TimeoutImmediate, delayMilliseconds = 0); @@ -76,7 +76,7 @@ CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, Timers: return CHIP_NO_ERROR; } -void WatchableEventManager::CancelTimer(Timers::OnCompleteFunct onComplete, void * appState) +void WatchableEventManager::CancelTimer(TimerCompleteCallback onComplete, void * appState) { Timer * timer = mTimerList.Remove(onComplete, appState); VerifyOrReturn(timer != nullptr); @@ -85,7 +85,7 @@ void WatchableEventManager::CancelTimer(Timers::OnCompleteFunct onComplete, void timer->Release(); } -CHIP_ERROR WatchableEventManager::ScheduleWork(Timers::OnCompleteFunct onComplete, void * appState) +CHIP_ERROR WatchableEventManager::ScheduleWork(TimerCompleteCallback onComplete, void * appState) { Timer * timer = Timer::New(*mSystemLayer, 0, onComplete, appState); VerifyOrReturnError(timer != nullptr, CHIP_ERROR_NO_MEMORY); @@ -165,7 +165,7 @@ CHIP_ERROR WatchableEventManager::AddEventHandlerDelegate(LwIPEventHandlerDelega */ CHIP_ERROR WatchableEventManager::PostEvent(Object & aTarget, EventType aEventType, uintptr_t aArgument) { - VerifyOrReturnError(mSystemLayer->State() == kLayerState_Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mSystemLayer->State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); // Sanity check that this instance and the target layer haven't been "crossed". VerifyOrDieWithMsg(aTarget.IsRetained(*mSystemLayer), chipSystemLayer, "wrong poster! [target %p != this %p]", @@ -187,7 +187,7 @@ CHIP_ERROR WatchableEventManager::PostEvent(Object & aTarget, EventType aEventTy */ CHIP_ERROR WatchableEventManager::DispatchEvents() { - VerifyOrReturnError(mSystemLayer->State() == kLayerState_Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mSystemLayer->State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); return PlatformEventing::DispatchEvents(*mSystemLayer); } @@ -203,7 +203,7 @@ CHIP_ERROR WatchableEventManager::DispatchEvents() */ CHIP_ERROR WatchableEventManager::DispatchEvent(Event aEvent) { - VerifyOrReturnError(mSystemLayer->State() == kLayerState_Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mSystemLayer->State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); return PlatformEventing::DispatchEvent(*mSystemLayer, aEvent); } @@ -220,7 +220,7 @@ CHIP_ERROR WatchableEventManager::DispatchEvent(Event aEvent) */ CHIP_ERROR WatchableEventManager::HandleEvent(Object & aTarget, EventType aEventType, uintptr_t aArgument) { - VerifyOrReturnError(mSystemLayer->State() == kLayerState_Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mSystemLayer->State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); // Sanity check that this instance and the target layer haven't been "crossed". VerifyOrDieWithMsg(aTarget.IsRetained(*mSystemLayer), chipSystemLayer, "wrong handler! [target %p != this %p]", @@ -266,7 +266,7 @@ CHIP_ERROR WatchableEventManager::HandleEvent(Object & aTarget, EventType aEvent */ CHIP_ERROR WatchableEventManager::StartPlatformTimer(uint32_t aDelayMilliseconds) { - VerifyOrReturnError(mSystemLayer->State() == kLayerState_Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mSystemLayer->State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); return PlatformEventing::StartTimer(*mSystemLayer, aDelayMilliseconds); } @@ -287,7 +287,7 @@ CHIP_ERROR WatchableEventManager::StartPlatformTimer(uint32_t aDelayMilliseconds */ CHIP_ERROR WatchableEventManager::HandlePlatformTimer() { - VerifyOrReturnError(mSystemLayer->State() == kLayerState_Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mSystemLayer->State() == LayerState::kInitialized, CHIP_ERROR_INCORRECT_STATE); // Expire each timer in turn until an unexpired timer is reached or the timerlist is emptied. We set the current expiration // time outside the loop; that way timers set after the current tick will not be executed within this expiration window diff --git a/src/system/WatchableEventManagerLwIP.h b/src/system/WatchableEventManagerLwIP.h index 27132f687939bb..8fc0e6563dcedc 100644 --- a/src/system/WatchableEventManagerLwIP.h +++ b/src/system/WatchableEventManagerLwIP.h @@ -56,9 +56,9 @@ class WatchableEventManager void Signal(); // Timer ‘overrides’. - CHIP_ERROR StartTimer(uint32_t delayMilliseconds, Timers::OnCompleteFunct onComplete, void * appState); - void CancelTimer(Timers::OnCompleteFunct onComplete, void * appState); - CHIP_ERROR ScheduleWork(Timers::OnCompleteFunct onComplete, void * appState); + CHIP_ERROR StartTimer(uint32_t delayMilliseconds, TimerCompleteCallback onComplete, void * appState); + void CancelTimer(TimerCompleteCallback onComplete, void * appState); + CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState); // Platform implementation. // typedef CHIP_ERROR (*EventHandler)(Object & aTarget, EventType aEventType, uintptr_t aArgument); diff --git a/src/system/WatchableEventManagerSelect.cpp b/src/system/WatchableEventManagerSelect.cpp index fef6d30709c767..cc986cc74893e2 100644 --- a/src/system/WatchableEventManagerSelect.cpp +++ b/src/system/WatchableEventManagerSelect.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include @@ -57,19 +56,20 @@ CHIP_ERROR WatchableEventManager::Init(Layer & systemLayer) RegisterPOSIXErrorFormatter(); mSystemLayer = &systemLayer; - mMaxFd = -1; - FD_ZERO(&mRequest.mReadSet); - FD_ZERO(&mRequest.mWriteSet); - FD_ZERO(&mRequest.mErrorSet); ReturnErrorOnFailure(mTimerList.Init()); + for (auto & w : mSocketWatchPool) + { + w.Clear(); + } + #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING mHandleSelectThread = PTHREAD_NULL; #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING // Create an event to allow an arbitrary thread to wake the thread in the select loop. - return mWakeEvent.Open(*this); + return mWakeEvent.Open(systemLayer); } CHIP_ERROR WatchableEventManager::Shutdown() @@ -89,7 +89,7 @@ CHIP_ERROR WatchableEventManager::Shutdown() timer->Release(); } - mWakeEvent.Close(); + mWakeEvent.Close(*mSystemLayer); mSystemLayer = nullptr; return CHIP_NO_ERROR; } @@ -120,7 +120,7 @@ void WatchableEventManager::Signal() } } -CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, Timers::OnCompleteFunct onComplete, void * appState) +CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, TimerCompleteCallback onComplete, void * appState) { CHIP_SYSTEM_FAULT_INJECT(FaultInjection::kFault_TimeoutImmediate, delayMilliseconds = 0); @@ -161,7 +161,7 @@ CHIP_ERROR WatchableEventManager::StartTimer(uint32_t delayMilliseconds, Timers: return CHIP_NO_ERROR; } -void WatchableEventManager::CancelTimer(Timers::OnCompleteFunct onComplete, void * appState) +void WatchableEventManager::CancelTimer(TimerCompleteCallback onComplete, void * appState) { Timer * timer = mTimerList.Remove(onComplete, appState); VerifyOrReturn(timer != nullptr); @@ -180,7 +180,7 @@ void WatchableEventManager::CancelTimer(Timers::OnCompleteFunct onComplete, void Signal(); } -CHIP_ERROR WatchableEventManager::ScheduleWork(Timers::OnCompleteFunct onComplete, void * appState) +CHIP_ERROR WatchableEventManager::ScheduleWork(TimerCompleteCallback onComplete, void * appState) { CancelTimer(onComplete, appState); @@ -207,6 +207,90 @@ CHIP_ERROR WatchableEventManager::ScheduleWork(Timers::OnCompleteFunct onComplet return CHIP_NO_ERROR; } +CHIP_ERROR WatchableEventManager::StartWatchingSocket(int fd, SocketWatchToken * tokenOut) +{ + // Find a free slot. + SocketWatch * watch = nullptr; + for (auto & w : mSocketWatchPool) + { + if (w.mFD == fd) + { + // Duplicate registration is an error. + return CHIP_ERROR_INVALID_ARGUMENT; + } + else if ((w.mFD == kInvalidFd) && (watch == nullptr)) + { + watch = &w; + } + } + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_ENDPOINT_POOL_FULL); + + watch->mFD = fd; + + *tokenOut = reinterpret_cast(watch); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WatchableEventManager::SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data) +{ + SocketWatch * watch = reinterpret_cast(token); + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + watch->mCallback = callback; + watch->mCallbackData = data; + return CHIP_NO_ERROR; +} + +CHIP_ERROR WatchableEventManager::RequestCallbackOnPendingRead(SocketWatchToken token) +{ + SocketWatch * watch = reinterpret_cast(token); + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + watch->mPendingIO.Set(SocketEventFlags::kRead); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WatchableEventManager::RequestCallbackOnPendingWrite(SocketWatchToken token) +{ + SocketWatch * watch = reinterpret_cast(token); + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + watch->mPendingIO.Set(SocketEventFlags::kWrite); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WatchableEventManager::ClearCallbackOnPendingRead(SocketWatchToken token) +{ + SocketWatch * watch = reinterpret_cast(token); + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + watch->mPendingIO.Clear(SocketEventFlags::kRead); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WatchableEventManager::ClearCallbackOnPendingWrite(SocketWatchToken token) +{ + SocketWatch * watch = reinterpret_cast(token); + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + watch->mPendingIO.Clear(SocketEventFlags::kWrite); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WatchableEventManager::StopWatchingSocket(SocketWatchToken * tokenInOut) +{ + SocketWatch * watch = reinterpret_cast(*tokenInOut); + *tokenInOut = InvalidSocketWatchToken(); + + VerifyOrReturnError(watch != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(watch->mFD >= 0, CHIP_ERROR_INCORRECT_STATE); + + watch->Clear(); + + // Wake the thread calling select so that it stops selecting on the socket. + Signal(); + + return CHIP_NO_ERROR; +} + /** * Set the read, write or exception bit flags for the specified socket based on its status in * the corresponding file descriptor sets. @@ -238,59 +322,6 @@ SocketEvents WatchableEventManager::SocketEventsFromFDs(int socket, const fd_set return res; } -bool WatchableEventManager::HasAnyRequest(int fd) -{ - return FD_ISSET(fd, &mRequest.mReadSet) || FD_ISSET(fd, &mRequest.mWriteSet) || FD_ISSET(fd, &mRequest.mErrorSet); -} - -CHIP_ERROR WatchableEventManager::SetRequest(int fd, fd_set * fds) -{ - FD_SET(fd, fds); - if (fd > mMaxFd) - { - mMaxFd = fd; - } - // Wake the thread calling select so that it starts selecting on the new socket. - Signal(); - return CHIP_NO_ERROR; -} - -CHIP_ERROR WatchableEventManager::ClearRequest(int fd, fd_set * fds) -{ - FD_CLR(fd, fds); - if (fd == mMaxFd) - { - MaybeLowerMaxFd(); - } - // Wake the thread calling select so that it starts selecting on the new socket. - Signal(); - return CHIP_NO_ERROR; -} - -void WatchableEventManager::ResetRequests(int fd) -{ - FD_CLR(fd, &mRequest.mReadSet); - FD_CLR(fd, &mRequest.mWriteSet); - FD_CLR(fd, &mRequest.mErrorSet); - if (fd == mMaxFd) - { - MaybeLowerMaxFd(); - } -} - -void WatchableEventManager::MaybeLowerMaxFd() -{ - int fd; - for (fd = mMaxFd; fd >= 0; --fd) - { - if (HasAnyRequest(fd)) - { - break; - } - } - mMaxFd = fd; -} - void WatchableEventManager::PrepareEvents() { assertChipStackLockedByCurrentThread(); @@ -301,9 +332,9 @@ void WatchableEventManager::PrepareEvents() Clock::MonotonicMilliseconds awakenTime = currentTime + kMaxTimeout; Timer * timer = mTimerList.Earliest(); - if (timer && Clock::IsEarlier(timer->mAwakenTime, awakenTime)) + if (timer && Clock::IsEarlier(timer->AwakenTime(), awakenTime)) { - awakenTime = timer->mAwakenTime; + awakenTime = timer->AwakenTime(); } const Clock::MonotonicMilliseconds sleepTime = (awakenTime > currentTime) ? (awakenTime - currentTime) : 0; @@ -313,7 +344,28 @@ void WatchableEventManager::PrepareEvents() chip::Mdns::GetMdnsTimeout(mNextTimeout); #endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS && !__ZEPHYR__ - mSelected = mRequest; + mMaxFd = -1; + FD_ZERO(&mSelected.mReadSet); + FD_ZERO(&mSelected.mWriteSet); + FD_ZERO(&mSelected.mErrorSet); + for (auto & w : mSocketWatchPool) + { + if (w.mFD != kInvalidFd) + { + if (mMaxFd < w.mFD) + { + mMaxFd = w.mFD; + } + if (w.mPendingIO.Has(SocketEventFlags::kRead)) + { + FD_SET(w.mFD, &mSelected.mReadSet); + } + if (w.mPendingIO.Has(SocketEventFlags::kWrite)) + { + FD_SET(w.mFD, &mSelected.mWriteSet); + } + } + } } void WatchableEventManager::WaitForEvents() @@ -346,21 +398,15 @@ void WatchableEventManager::HandleEvents() timer->HandleComplete(); } - for (WatchableSocket * watchable = mAttachedSockets; watchable != nullptr; watchable = watchable->mAttachedNext) - { - watchable->SetPendingIO( - SocketEventsFromFDs(watchable->GetFD(), mSelected.mReadSet, mSelected.mWriteSet, mSelected.mErrorSet)); - } - - WatchableSocket * nextWatchableSocket = mAttachedSockets; - while (nextWatchableSocket != nullptr) + for (auto & w : mSocketWatchPool) { - WatchableSocket * currentWatchable = nextWatchableSocket; - nextWatchableSocket = nextWatchableSocket->mAttachedNext; - - if (currentWatchable->mPendingIO.HasAny()) + if (w.mFD != kInvalidFd) { - currentWatchable->InvokeCallback(); + SocketEvents events = SocketEventsFromFDs(w.mFD, mSelected.mReadSet, mSelected.mWriteSet, mSelected.mErrorSet); + if (events.HasAny() && w.mCallback != nullptr) + { + w.mCallback(events, w.mCallbackData); + } } } @@ -381,5 +427,13 @@ void WatchableEventManager::HandleTimerComplete(Timer * timer) } #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH +void WatchableEventManager::SocketWatch::Clear() +{ + mFD = kInvalidFd; + mPendingIO.ClearAll(); + mCallback = nullptr; + mCallbackData = 0; +} + } // namespace System } // namespace chip diff --git a/src/system/WatchableEventManagerSelect.h b/src/system/WatchableEventManagerSelect.h index 57cd1eeca1e77d..05d75ae6bfbaec 100644 --- a/src/system/WatchableEventManagerSelect.h +++ b/src/system/WatchableEventManagerSelect.h @@ -34,18 +34,11 @@ #include #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING -#include -#include -#include #include namespace chip { namespace System { -class Layer; -class Timer; -class WatchableSocket; - class WatchableEventManager { public: @@ -55,9 +48,19 @@ class WatchableEventManager void Signal(); // Timer ‘overrides’. - CHIP_ERROR StartTimer(uint32_t delayMilliseconds, Timers::OnCompleteFunct onComplete, void * appState); - void CancelTimer(Timers::OnCompleteFunct onComplete, void * appState); - CHIP_ERROR ScheduleWork(Timers::OnCompleteFunct onComplete, void * appState); + CHIP_ERROR StartTimer(uint32_t delayMilliseconds, TimerCompleteCallback onComplete, void * appState); + void CancelTimer(TimerCompleteCallback onComplete, void * appState); + CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState); + + // Socket watch ‘overrides’. + CHIP_ERROR StartWatchingSocket(int fd, SocketWatchToken * tokenOut); + CHIP_ERROR SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data); + CHIP_ERROR RequestCallbackOnPendingRead(SocketWatchToken token); + CHIP_ERROR RequestCallbackOnPendingWrite(SocketWatchToken token); + CHIP_ERROR ClearCallbackOnPendingRead(SocketWatchToken token); + CHIP_ERROR ClearCallbackOnPendingWrite(SocketWatchToken token); + CHIP_ERROR StopWatchingSocket(SocketWatchToken * tokenInOut); + SocketWatchToken InvalidSocketWatchToken() { return reinterpret_cast(nullptr); } // Platform implementation. void EventLoopBegins() {} @@ -75,13 +78,22 @@ class WatchableEventManager #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH protected: - friend class WatchableSocket; + static constexpr int kSocketWatchMax = (INET_CONFIG_ENABLE_RAW_ENDPOINT ? INET_CONFIG_NUM_RAW_ENDPOINTS : 0) + + (INET_CONFIG_ENABLE_TCP_ENDPOINT ? INET_CONFIG_NUM_TCP_ENDPOINTS : 0) + + (INET_CONFIG_ENABLE_UDP_ENDPOINT ? INET_CONFIG_NUM_UDP_ENDPOINTS : 0) + + (INET_CONFIG_ENABLE_DNS_RESOLVER ? INET_CONFIG_NUM_DNS_RESOLVERS : 0); - CHIP_ERROR SetRequest(int fd, fd_set * fds); - CHIP_ERROR ClearRequest(int fd, fd_set * fds); + struct SocketWatch + { + void Clear(); + int mFD; + SocketEvents mPendingIO; + SocketWatchCallback mCallback; + intptr_t mCallbackData; + }; + SocketWatch mSocketWatchPool[kSocketWatchMax]; - Layer * mSystemLayer = nullptr; - WatchableSocket * mAttachedSockets = nullptr; + Layer * mSystemLayer = nullptr; Timer::MutexedList mTimerList; timeval mNextTimeout; @@ -92,7 +104,6 @@ class WatchableEventManager fd_set mWriteSet; fd_set mErrorSet; }; - SelectSets mRequest; SelectSets mSelected; int mMaxFd; @@ -108,11 +119,6 @@ class WatchableEventManager #if CHIP_SYSTEM_CONFIG_USE_DISPATCH dispatch_queue_t mDispatchQueue; #endif - -private: - bool HasAnyRequest(int fd); - void MaybeLowerMaxFd(); - void ResetRequests(int fd); }; } // namespace System diff --git a/src/system/WatchableSocket.h b/src/system/WatchableSocket.h deleted file mode 100644 index 73615e07971428..00000000000000 --- a/src/system/WatchableSocket.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * - * Copyright (c) 2020-2021 Project CHIP Authors - * - * 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 declares the WatchableSocket abstraction of socket (file descriptor) events. - */ - -#pragma once - -// Include configuration headers -#include - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS - -#include -#include - -#include -#include -#include -#include - -namespace chip { - -namespace System { - -class Layer; -class WatchableEventManager; - -enum class SocketEventFlags : uint8_t -{ - kRead = 0x1, /**< Bit flag indicating if there is a read event on a socket. */ - kWrite = 0x2, /**< Bit flag indicating if there is a write event on a socket. */ - kExcept = 0x4, /**< Bit flag indicating if there is an exceptional condition on a socket (e.g. out-of-band data). */ - kError = 0x8, /**< Bit flag indicating if there is an error event on a socket. */ -}; - -using SocketEvents = BitFlags; - -/** - * @class WatchableSocket - * - * Users of a WatchableSocket should interact with it using the methods defined by WatchableSocketBasis. - * - * Implementations of WatchableSocket must inherit `public WatchableSocketBasis` - * and provide the following methods, which are invoked by the corresponding WatchableSocketBasis functions: - * - * void OnInit() - * CHIP_ERROR OnAttach() - * CHIP_ERROR OnRelease() - * CHIP_ERROR OnRequestCallbackOnPendingRead() - * CHIP_ERROR OnRequestCallbackOnPendingWrite() - * CHIP_ERROR OnClearCallbackOnPendingRead() - * CHIP_ERROR OnClearCallbackOnPendingWrite() - * - */ -class WatchableSocket; - -/** - * @class WatchableSocketBasis - * - * This class provides the interface used by platform-independent parts of the CHIP stack. - * - * The general pattern for using a WatchableSocket s is: - * - * s.Init(WatchableEventManager) - * s.Attach(fd) - * s.SetCallback(callbackFunction, callbackData) - * s.{Request|Clear}CallbackOnPending{Read|Write}() - * ... - * s.Close() - * - */ -template -class WatchableSocketBasis -{ -public: - enum : int - { - kInvalidFd = -1 - }; - - /** - * Initialize a WatchableSocket. - * - * @param[in] manager Reference to shared socket-event state (which must already have been initialized). - */ - void Init(WatchableEventManager & manager) - { - mFD = kInvalidFd; - mPendingIO.ClearAll(); - mCallback = nullptr; - mCallbackData = 0; - mSharedState = &manager; - static_cast(this)->OnInit(); - } - - /** - * Associate this WatchableSocket with a file descriptor. - * - * @param[in] fd An open file descriptor. - */ - CHIP_ERROR Attach(int fd) - { - mFD = fd; - return static_cast(this)->OnAttach(); - } - - /** - * Disassociate this WatchableSocket from its file descriptor. - * - * @returns the file descriptor. - */ - int ReleaseFD() - { - static_cast(this)->OnRelease(); - const int fd = mFD; - mFD = kInvalidFd; - return fd; - } - - /** - * Close the associated file descriptor. - */ - void Close() { VerifyOrDie(close(ReleaseFD()) == 0); } - - /** - * Test whether there is an associated open file descriptor. - */ - bool HasFD() const { return mFD >= 0; } - - /** - * Get the associated open file descriptor. - */ - int GetFD() const { return mFD; } - - /** - * Indicate that the socket-event system should invoke the registered callback when the file descriptor is ready to read. - */ - CHIP_ERROR RequestCallbackOnPendingRead() { return static_cast(this)->OnRequestCallbackOnPendingRead(); } - - /** - * Indicate that the socket-event system should invoke the registered callback when the file descriptor is ready to write. - */ - CHIP_ERROR RequestCallbackOnPendingWrite(bool request = true) - { - return static_cast(this)->OnRequestCallbackOnPendingWrite(); - } - - /** - * Indicate that the socket-event system need not invoke the registered callback when the file descriptor is ready to read. - */ - CHIP_ERROR ClearCallbackOnPendingRead() { return static_cast(this)->OnClearCallbackOnPendingRead(); } - - /** - * Indicate that the socket-event system need not invoke the registered callback when the file descriptor is ready to write. - */ - CHIP_ERROR ClearCallbackOnPendingWrite() { return static_cast(this)->OnClearCallbackOnPendingWrite(); } - - /** - * The callback is passed a reference to the WatchableSocket for which the requested event(s) are ready. - */ - using Callback = void (*)(WatchableSocket & socket); - - /** - * Register a callback function. - * - * The callback will be invoked (with the CHIP stack lock held) when requested event(s) are ready. - * - * @param[in] callback Function invoked when event(s) are ready. - * @param[in] data Arbitrary data accessible within a callback function. - */ - void SetCallback(Callback callback, intptr_t data) - { - mCallback = callback; - mCallbackData = data; - } - - /** - * Retrieve callback data. - * - * @returns the pointer supplied to SetCallback(). - */ - intptr_t GetCallbackData() const { return mCallbackData; } - - /** - * Inside a callback function, get the pending SocketEvents. - */ - SocketEvents GetPendingEvents() const { return mPendingIO; } - - /** - * Inside a callback function, test whether the file descriptor is ready to read. - */ - bool HasPendingRead() const { return mPendingIO.Has(SocketEventFlags::kRead); } - - /** - * Inside a callback function, test whether the file descriptor is ready to write. - */ - bool HasPendingWrite() const { return mPendingIO.Has(SocketEventFlags::kWrite); } - - /** - * Inside a callback function, test whether there is an exceptional condition (e.g. out-of-band data) - * associated with the file descriptor. - */ - bool HasPendingException() const { return mPendingIO.Has(SocketEventFlags::kExcept); } - - /** - * Inside a callback function, test whether there is an error condition associated with the file descriptor. - */ - bool HasPendingError() const { return mPendingIO.Has(SocketEventFlags::kError); } - - /** - * Inside a callback function, reset the set of pending events. - */ - void ClearPendingIO() { mPendingIO.ClearAll(); } - -protected: - void InvokeCallback() - { - if (mCallback != nullptr) - { - mCallback(static_cast(*this)); - } - } - - int mFD; - SocketEvents mPendingIO; - Callback mCallback; - intptr_t mCallbackData; - WatchableEventManager * mSharedState; -}; - -} // namespace System -} // namespace chip - -#define INCLUDING_CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE 1 -#ifdef CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE -#include CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE -#else // CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE -#include -#endif // CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE -#undef INCLUDING_CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE - -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS diff --git a/src/system/WatchableSocketLibevent.cpp b/src/system/WatchableSocketLibevent.cpp deleted file mode 100644 index f25213e5f114a3..00000000000000 --- a/src/system/WatchableSocketLibevent.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * - * 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 WatchableSocket using libevent. - */ - -#include -#include -#include -#include -#include -#include - -namespace chip { -namespace System { - -void WatchableSocket::OnInit() -{ - mEvent = nullptr; - mActiveNext = nullptr; -} - -CHIP_ERROR WatchableSocket::OnAttach() -{ - VerifyOrReturnError(evutil_make_socket_nonblocking(mFD) == 0, MapErrorPOSIX(errno)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR WatchableSocket::OnRelease() -{ - CHIP_ERROR status = UpdateWatch(0); - mSharedState->RemoveFromQueueIfPresent(this); - return status; -} - -CHIP_ERROR WatchableSocket::SetWatch(short eventFlags) -{ - const short oldFlags = mEvent ? event_get_events(mEvent) : 0; - const short newFlags = static_cast(EV_PERSIST | oldFlags | eventFlags); - if (oldFlags != newFlags) - { - return UpdateWatch(newFlags); - } - return CHIP_NO_ERROR; -} - -CHIP_ERROR WatchableSocket::ClearWatch(short eventFlags) -{ - const short oldFlags = mEvent ? event_get_events(mEvent) : 0; - const short newFlags = static_cast(EV_PERSIST | (oldFlags & ~eventFlags)); - if (oldFlags != newFlags) - { - return UpdateWatch(newFlags); - } - return CHIP_NO_ERROR; -} - -CHIP_ERROR WatchableSocket::UpdateWatch(short eventFlags) -{ - if (mEvent) - { - event_del(mEvent); - event_free(mEvent); - mEvent = nullptr; - } - if (eventFlags) - { - event_base * const base = mSharedState->mEventBase; - mEvent = event_new(base, mFD, eventFlags, WatchableEventManager::LibeventCallbackHandler, this); - VerifyOrReturnError(mEvent != nullptr, CHIP_ERROR_NO_MEMORY); - VerifyOrReturnError(event_add(mEvent, nullptr) == 0, CHIP_ERROR_INTERNAL); - } - return CHIP_NO_ERROR; -} - -} // namespace System -} // namespace chip diff --git a/src/system/WatchableSocketLibevent.h b/src/system/WatchableSocketLibevent.h deleted file mode 100644 index b3f516a48085af..00000000000000 --- a/src/system/WatchableSocketLibevent.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * - * 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 declares an implementation of WatchableEventManager using libevent. - */ - -#pragma once - -#if !INCLUDING_CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE -#error "This file should only be included from " -#include -#endif // !INCLUDING_CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE - -#include - -namespace chip { - -namespace System { - -class WatchableEventManager; - -class WatchableSocket : public WatchableSocketBasis -{ -public: - void OnInit(); - CHIP_ERROR OnAttach(); - CHIP_ERROR OnRelease(); - CHIP_ERROR OnRequestCallbackOnPendingRead() { return SetWatch(EV_READ); } - CHIP_ERROR OnRequestCallbackOnPendingWrite() { return SetWatch(EV_WRITE); } - CHIP_ERROR OnClearCallbackOnPendingRead() { return ClearWatch(EV_READ); } - CHIP_ERROR OnClearCallbackOnPendingWrite() { return ClearWatch(EV_WRITE); } - -private: - friend class WatchableEventManager; - - CHIP_ERROR SetWatch(short eventFlags); - CHIP_ERROR ClearWatch(short eventFlags); - CHIP_ERROR UpdateWatch(short eventFlags); - - WatchableSocket * mActiveNext; ///< Next element in the list of sockets activated by libevent. - struct event * mEvent; ///< libevent state. -}; - -} // namespace System -} // namespace chip diff --git a/src/system/WatchableSocketSelect.cpp b/src/system/WatchableSocketSelect.cpp deleted file mode 100644 index 65ce2fb71a047b..00000000000000 --- a/src/system/WatchableSocketSelect.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * Copyright (c) 2020-2021 Project CHIP Authors - * Copyright (c) 2014-2017 Nest Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * This file implements WatchableSocket using select(). - */ - -#include -#include -#include -#include -#include - -#include - -namespace chip { -namespace System { - -CHIP_ERROR WatchableSocket::OnAttach() -{ - mSharedState->ResetRequests(mFD); - - VerifyOrReturnError(mAttachedNext == nullptr, CHIP_ERROR_INCORRECT_STATE); - mAttachedNext = mSharedState->mAttachedSockets; - mSharedState->mAttachedSockets = this; - return CHIP_NO_ERROR; -} - -CHIP_ERROR WatchableSocket::OnRelease() -{ - VerifyOrReturnError(mFD >= 0, CHIP_ERROR_INCORRECT_STATE); - mSharedState->ResetRequests(mFD); - - WatchableSocket ** pp = &mSharedState->mAttachedSockets; - while (*pp != nullptr) - { - if (*pp == this) - { - *pp = this->mAttachedNext; - break; - } - pp = &(*pp)->mAttachedNext; - } - - // Wake the thread calling select so that it stops selecting on the socket. - mSharedState->Signal(); - return CHIP_NO_ERROR; -} - -CHIP_ERROR WatchableSocket::OnRequestCallbackOnPendingRead() -{ - return mSharedState->SetRequest(mFD, &mSharedState->mRequest.mReadSet); -} - -CHIP_ERROR WatchableSocket::OnRequestCallbackOnPendingWrite() -{ - return mSharedState->SetRequest(mFD, &mSharedState->mRequest.mWriteSet); -} - -CHIP_ERROR WatchableSocket::OnClearCallbackOnPendingRead() -{ - return mSharedState->ClearRequest(mFD, &mSharedState->mRequest.mReadSet); -} - -CHIP_ERROR WatchableSocket::OnClearCallbackOnPendingWrite() -{ - return mSharedState->ClearRequest(mFD, &mSharedState->mRequest.mWriteSet); -} - -/** - * Sets the bit for the specified file descriptor in the given sets of file descriptors. - * - * @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 WatchableSocket::SetFDs(int & nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds) -{ - if (mFD >= 0) - { - int r = FD_ISSET(mFD, &mSharedState->mRequest.mReadSet); - int w = FD_ISSET(mFD, &mSharedState->mRequest.mWriteSet); - int e = FD_ISSET(mFD, &mSharedState->mRequest.mErrorSet); - if (r) - FD_SET(mFD, readfds); - if (w) - FD_SET(mFD, writefds); - if (e) - FD_SET(mFD, exceptfds); - if ((r || w || e) && mFD >= nfds) - nfds = mFD + 1; - } -} - -} // namespace System -} // namespace chip diff --git a/src/system/WatchableSocketSelect.h b/src/system/WatchableSocketSelect.h deleted file mode 100644 index 2d32f98828ef5c..00000000000000 --- a/src/system/WatchableSocketSelect.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * - * 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 declares an implementation of WatchableSocket using select(). - */ - -#pragma once - -#if !INCLUDING_CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE -#error "This file should only be included from " -#include -#endif // !INCLUDING_CHIP_SYSTEM_WATCHABLE_SOCKET_CONFIG_FILE - -#include - -#include -#include - -namespace chip { -namespace System { - -class WatchableSocket : public WatchableSocketBasis -{ -public: - void OnInit() { mAttachedNext = nullptr; } - CHIP_ERROR OnAttach(); - CHIP_ERROR OnRelease(); - - CHIP_ERROR OnRequestCallbackOnPendingRead(); - CHIP_ERROR OnRequestCallbackOnPendingWrite(); - CHIP_ERROR OnClearCallbackOnPendingRead(); - CHIP_ERROR OnClearCallbackOnPendingWrite(); - - void SetPendingIO(SocketEvents events) { mPendingIO = events; } - void SetFDs(int & nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds); - -private: - friend class WatchableEventManager; - - WatchableSocket * mAttachedNext; ///< Next element in the list of sockets attached to the WatchableEventManager. -}; - -} // namespace System -} // namespace chip diff --git a/src/system/tests/TestSystemTimer.cpp b/src/system/tests/TestSystemTimer.cpp index bb3e68d07b943b..df76ee7f07dfbb 100644 --- a/src/system/tests/TestSystemTimer.cpp +++ b/src/system/tests/TestSystemTimer.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #if CHIP_SYSTEM_CONFIG_USE_LWIP #include @@ -59,7 +58,7 @@ static void ServiceEvents(Layer & aLayer) #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK #if CHIP_SYSTEM_CONFIG_USE_LWIP - if (aLayer.State() == kLayerState_Initialized) + if (aLayer.State() == LayerState::kInitialized) { aLayer.WatchableEventsManager().HandlePlatformTimer(); } diff --git a/src/system/tests/TestSystemWakeEvent.cpp b/src/system/tests/TestSystemWakeEvent.cpp index 54d2eb5cd5b34d..de017b2afb52e7 100644 --- a/src/system/tests/TestSystemWakeEvent.cpp +++ b/src/system/tests/TestSystemWakeEvent.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #if CHIP_SYSTEM_CONFIG_POSIX_LOCKING #include @@ -58,18 +57,19 @@ namespace { struct TestContext { ::chip::System::Layer mSystemLayer; - WatchableEventManager mWatchableEvents; WakeEvent mWakeEvent; fd_set mReadSet; fd_set mWriteSet; fd_set mErrorSet; - TestContext() - { - (void) mWatchableEvents.Init(mSystemLayer); - mWakeEvent.Open(mWatchableEvents); + TestContext() { + mSystemLayer.Init(); + mWakeEvent.Open(mSystemLayer); + } + ~TestContext() { + mWakeEvent.Close(mSystemLayer); + mSystemLayer.Shutdown(); } - ~TestContext() { mWakeEvent.Close(); } int SelectWakeEvent(timeval timeout = {}) { @@ -145,12 +145,12 @@ void TestBlockingSelect(nlTestSuite *, void *) {} void TestClose(nlTestSuite * inSuite, void * aContext) { TestContext & lContext = *static_cast(aContext); - lContext.mWakeEvent.Close(); + lContext.mWakeEvent.Close(lContext.mSystemLayer); const auto notifFD = WakeEventTest::GetReadFD(lContext.mWakeEvent); // Check that Close() has cleaned up itself and reopen is possible - NL_TEST_ASSERT(inSuite, lContext.mWakeEvent.Open(lContext.mWatchableEvents) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, lContext.mWakeEvent.Open(lContext.mSystemLayer) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, notifFD < 0); } } // namespace @@ -172,13 +172,7 @@ static const nlTest sTests[] = }; // clang-format on -// clang-format off -static nlTestSuite kTheSuite = -{ - "chip-system-wake-event", - sTests -}; -// clang-format on +static nlTestSuite kTheSuite = { "chip-system-wake-event", sTests }; int TestSystemWakeEvent(void) {