Skip to content

Commit

Permalink
Listen for group messages on all relevant interfaces in the sockets i…
Browse files Browse the repository at this point in the history
…mplementation. (project-chip#21611)

* Listen for group messages on all relevant interfaces in the sockets implementation.

We were listening on the "default" interface if MulticastGroupJoinLeave got
called for an enpoint that was bound to the wildcard interface.  But that does
not work in some situation (e.g. on Mac).

Instead, detect that we're dealing with the wildcard interface, and
explicitly iterate over all viable interfaces.

* Fix build on MbedOS.
  • Loading branch information
bzbarsky-apple authored and isiu-apple committed Sep 16, 2022
1 parent f7e73c9 commit 109a8b3
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/darwin-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jobs:
./scripts/run_in_build_env.sh \
"./scripts/tests/run_test_suite.py \
--chip-tool ./out/darwin-x64-darwin-framework-tool-${BUILD_VARIANT}/darwin-framework-tool \
--target-skip-glob '{TestGroupMessaging,TestAccessControlConstraints}' \
--target-skip-glob '{TestAccessControlConstraints}' \
run \
--iterations 1 \
--test-timeout-seconds 120 \
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ jobs:
./scripts/run_in_build_env.sh \
"./scripts/tests/run_test_suite.py \
--chip-tool ./out/darwin-x64-chip-tool${CHIP_TOOL_VARIANT}-${BUILD_VARIANT}/chip-tool \
--target-skip-glob '{TestGroupMessaging,Test_TC_DGTHREAD_2_1,Test_TC_DGTHREAD_2_2,Test_TC_DGTHREAD_2_3,Test_TC_DGTHREAD_2_4}' \
--target-skip-glob '{Test_TC_DGTHREAD_2_1,Test_TC_DGTHREAD_2_2,Test_TC_DGTHREAD_2_3,Test_TC_DGTHREAD_2_4}' \
run \
--iterations 1 \
--test-timeout-seconds 120 \
Expand Down
95 changes: 84 additions & 11 deletions src/inet/UDPEndPointImplSockets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
#define SOCK_CLOEXEC 0
#endif

// On MbedOS, INADDR_ANY does not seem to exist...
#ifndef INADDR_ANY
#define INADDR_ANY 0
#endif

#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS
#include "ZephyrSocket.h"
#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS
Expand Down Expand Up @@ -729,27 +734,39 @@ CHIP_ERROR UDPEndPointImplSockets::SetMulticastLoopback(IPVersion aIPVersion, bo

CHIP_ERROR UDPEndPointImplSockets::IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join)
{
IPAddress lInterfaceAddress;
bool lInterfaceAddressFound = false;
in_addr interfaceAddr;

for (InterfaceAddressIterator lAddressIterator; lAddressIterator.HasCurrent(); lAddressIterator.Next())
if (aInterfaceId.IsPresent())
{
IPAddress lCurrentAddress;
if ((lAddressIterator.GetInterfaceId() == aInterfaceId) && (lAddressIterator.GetAddress(lCurrentAddress) == CHIP_NO_ERROR))
IPAddress lInterfaceAddress;
bool lInterfaceAddressFound = false;

for (InterfaceAddressIterator lAddressIterator; lAddressIterator.HasCurrent(); lAddressIterator.Next())
{
if (lCurrentAddress.IsIPv4())
IPAddress lCurrentAddress;
if ((lAddressIterator.GetInterfaceId() == aInterfaceId) &&
(lAddressIterator.GetAddress(lCurrentAddress) == CHIP_NO_ERROR))
{
lInterfaceAddressFound = true;
lInterfaceAddress = lCurrentAddress;
break;
if (lCurrentAddress.IsIPv4())
{
lInterfaceAddressFound = true;
lInterfaceAddress = lCurrentAddress;
break;
}
}
}
VerifyOrReturnError(lInterfaceAddressFound, INET_ERROR_ADDRESS_NOT_FOUND);

interfaceAddr = lInterfaceAddress.ToIPv4();
}
else
{
interfaceAddr.s_addr = htonl(INADDR_ANY);
}
VerifyOrReturnError(lInterfaceAddressFound, INET_ERROR_ADDRESS_NOT_FOUND);

struct ip_mreq lMulticastRequest;
memset(&lMulticastRequest, 0, sizeof(lMulticastRequest));
lMulticastRequest.imr_interface = lInterfaceAddress.ToIPv4();
lMulticastRequest.imr_interface = interfaceAddr;
lMulticastRequest.imr_multiaddr = aAddress.ToIPv4();

const int command = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
Expand All @@ -773,6 +790,62 @@ CHIP_ERROR UDPEndPointImplSockets::IPv6JoinLeaveMulticastGroupImpl(InterfaceId a
#endif // CHIP_SYSTEM_CONFIG_USE_PLATFORM_MULTICAST_API

#ifdef IPV6_MULTICAST_IMPLEMENTED
if (!aInterfaceId.IsPresent())
{
// Do it on all the viable interfaces.
bool interfaceFound = false;

InterfaceIterator interfaceIt;
while (interfaceIt.Next())
{
if (!interfaceIt.SupportsMulticast() || !interfaceIt.IsUp())
{
continue;
}

InterfaceId interfaceId = interfaceIt.GetInterfaceId();

IPAddress ifAddr;
if (interfaceId.GetLinkLocalAddr(&ifAddr) != CHIP_NO_ERROR)
{
continue;
}

if (ifAddr.Type() != IPAddressType::kIPv6)
{
// Not the right sort of interface.
continue;
}

interfaceFound = true;

char ifName[InterfaceId::kMaxIfNameLength];
interfaceIt.GetInterfaceName(ifName, sizeof(ifName));

// Ignore errors here, except for logging, because we expect some of
// these interfaces to not work, and some (e.g. loopback) to always
// work.
CHIP_ERROR err = IPv6JoinLeaveMulticastGroupImpl(interfaceId, aAddress, join);
if (err == CHIP_NO_ERROR)
{
ChipLogDetail(Inet, " %s multicast group on interface %s", (join ? "Joined" : "Left"), ifName);
}
else
{
ChipLogError(Inet, " Failed to %s multicast group on interface %s", (join ? "join" : "leave"), ifName);
}
}

if (interfaceFound)
{
// Assume we're good.
return CHIP_NO_ERROR;
}

// Else go ahead and try to work with the default interface.
ChipLogError(Inet, "No valid IPv6 multicast interface found");
}

const InterfaceId::PlatformType lIfIndex = aInterfaceId.GetPlatformInterface();

struct ipv6_mreq lMulticastRequest;
Expand Down

0 comments on commit 109a8b3

Please sign in to comment.