diff --git a/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp b/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp index 39e6a91bcb1b04..641e86687bd009 100644 --- a/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp @@ -89,7 +89,12 @@ static void BoundDeviceChangedHandler(const EmberBindingTableEntry & binding, ch ChipLogError(NotSpecified, "OnOff command failed: %" CHIP_ERROR_FORMAT, error.Format()); }; - VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); + if (!peer_device) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } + VerifyOrDie(peer_device->ConnectionReady()); if (sSwitchOnOffState) { Clusters::OnOff::Commands::On::Type onCommand; diff --git a/examples/all-clusters-app/ameba/main/BindingHandler.cpp b/examples/all-clusters-app/ameba/main/BindingHandler.cpp index 1c0fef656c7913..dbd9429af23bcd 100644 --- a/examples/all-clusters-app/ameba/main/BindingHandler.cpp +++ b/examples/all-clusters-app/ameba/main/BindingHandler.cpp @@ -60,6 +60,11 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation // It should always enter here if isReadAttribute is true if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { + if (!peer_device) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->clusterId) { case Clusters::Identify::Id: @@ -105,6 +110,11 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation } else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { + if (!peer_device) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->clusterId) { case Clusters::Identify::Id: diff --git a/examples/all-clusters-app/nxp/mw320/binding-handler.cpp b/examples/all-clusters-app/nxp/mw320/binding-handler.cpp index e4a2df4d387249..9bbf3ddfc98e11 100644 --- a/examples/all-clusters-app/nxp/mw320/binding-handler.cpp +++ b/examples/all-clusters-app/nxp/mw320/binding-handler.cpp @@ -80,6 +80,12 @@ static void BoundDeviceChangedHandler(const EmberBindingTableEntry & binding, ch return; } + if (binding.type == MATTER_UNICAST_BINDING && peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } + if (binding.type == MATTER_UNICAST_BINDING && binding.local == 1 && binding.clusterId.value_or(Clusters::OnOff::Id) == Clusters::OnOff::Id) { diff --git a/examples/light-switch-app/ameba/main/BindingHandler.cpp b/examples/light-switch-app/ameba/main/BindingHandler.cpp index 580b2bec197a44..8ce2d1dd3bd4e3 100644 --- a/examples/light-switch-app/ameba/main/BindingHandler.cpp +++ b/examples/light-switch-app/ameba/main/BindingHandler.cpp @@ -124,6 +124,11 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation } else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->clusterId) { case Clusters::OnOff::Id: diff --git a/examples/light-switch-app/asr/src/BindingHandler.cpp b/examples/light-switch-app/asr/src/BindingHandler.cpp index b924292b42eef6..97009aaf599cbd 100644 --- a/examples/light-switch-app/asr/src/BindingHandler.cpp +++ b/examples/light-switch-app/asr/src/BindingHandler.cpp @@ -216,6 +216,11 @@ void BindingHandler::LightSwitchChangedHandler(const EmberBindingTableEntry & aB } else if (aBinding.type == MATTER_UNICAST_BINDING && !data->IsGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->ClusterId) { case Clusters::OnOff::Id: diff --git a/examples/light-switch-app/cc13x4_26x4/src/BindingHandler.cpp b/examples/light-switch-app/cc13x4_26x4/src/BindingHandler.cpp index 67fd1c9ed1dbea..0df70e50be3893 100644 --- a/examples/light-switch-app/cc13x4_26x4/src/BindingHandler.cpp +++ b/examples/light-switch-app/cc13x4_26x4/src/BindingHandler.cpp @@ -101,6 +101,11 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation } else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->clusterId) { case Clusters::OnOff::Id: diff --git a/examples/light-switch-app/esp32/main/BindingHandler.cpp b/examples/light-switch-app/esp32/main/BindingHandler.cpp index cc1a66a1e28878..e801dd7203c0a3 100644 --- a/examples/light-switch-app/esp32/main/BindingHandler.cpp +++ b/examples/light-switch-app/esp32/main/BindingHandler.cpp @@ -120,6 +120,11 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation } else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->clusterId) { case Clusters::OnOff::Id: diff --git a/examples/light-switch-app/genio/src/BindingHandler.cpp b/examples/light-switch-app/genio/src/BindingHandler.cpp index 218a44671486d7..274c65255d197d 100644 --- a/examples/light-switch-app/genio/src/BindingHandler.cpp +++ b/examples/light-switch-app/genio/src/BindingHandler.cpp @@ -130,6 +130,11 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation } else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->clusterId) { case Clusters::OnOff::Id: diff --git a/examples/light-switch-app/infineon/cyw30739/src/BindingHandler.cpp b/examples/light-switch-app/infineon/cyw30739/src/BindingHandler.cpp index 9b03d14745cdf4..2abc7126acdd12 100644 --- a/examples/light-switch-app/infineon/cyw30739/src/BindingHandler.cpp +++ b/examples/light-switch-app/infineon/cyw30739/src/BindingHandler.cpp @@ -230,6 +230,11 @@ void BindingHandler::LightSwitchChangedHandler(const EmberBindingTableEntry & bi } else if (binding.type == MATTER_UNICAST_BINDING && !data->IsGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->ClusterId) { case Clusters::OnOff::Id: diff --git a/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp b/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp index a63488a34e5c2e..0d0cdc5e82e07b 100644 --- a/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp +++ b/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp @@ -215,6 +215,11 @@ void BindingHandler::LightSwitchChangedHandler(const EmberBindingTableEntry & bi } else if (binding.type == MATTER_UNICAST_BINDING && !data->IsGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->ClusterId) { case Clusters::OnOff::Id: diff --git a/examples/light-switch-app/qpg/src/binding-handler.cpp b/examples/light-switch-app/qpg/src/binding-handler.cpp index f2a7c266d62338..b2c4296145041f 100644 --- a/examples/light-switch-app/qpg/src/binding-handler.cpp +++ b/examples/light-switch-app/qpg/src/binding-handler.cpp @@ -179,8 +179,7 @@ static void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Op case Clusters::OnOff::Id: case Clusters::LevelControl::Id: case Clusters::ColorControl::Id: - // TODO should not happen? - VerifyOrReturn(peer_device != nullptr, ChipLogError(NotSpecified, "Peer is nullptr")); + VerifyOrReturn(peer_device != nullptr, ChipLogProgress(NotSpecified, "Binding to self")); ProcessSwitchUnicastBindingCommand(data->commandId, binding, peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), data); diff --git a/examples/light-switch-app/silabs/src/BindingHandler.cpp b/examples/light-switch-app/silabs/src/BindingHandler.cpp index 56f7c306f989d8..042773b0180e4b 100644 --- a/examples/light-switch-app/silabs/src/BindingHandler.cpp +++ b/examples/light-switch-app/silabs/src/BindingHandler.cpp @@ -101,6 +101,11 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation } else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->clusterId) { case Clusters::OnOff::Id: diff --git a/examples/light-switch-app/telink/src/binding-handler.cpp b/examples/light-switch-app/telink/src/binding-handler.cpp index 22c83a8b9fd788..b3dd16f5210ec4 100644 --- a/examples/light-switch-app/telink/src/binding-handler.cpp +++ b/examples/light-switch-app/telink/src/binding-handler.cpp @@ -118,6 +118,11 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation // It should always enter here if isReadAttribute is true if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->clusterId) { case Clusters::Identify::Id: @@ -142,6 +147,11 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation } else if (binding.type == MATTER_UNICAST_BINDING && !data->isGroup) { + if (peer_device == nullptr) + { + ChipLogProgress(NotSpecified, "Binding to self"); + return; + } switch (data->clusterId) { case Clusters::Identify::Id: diff --git a/src/app/clusters/bindings/BindingManager.cpp b/src/app/clusters/bindings/BindingManager.cpp index 936324c19e045c..1274ab07712247 100644 --- a/src/app/clusters/bindings/BindingManager.cpp +++ b/src/app/clusters/bindings/BindingManager.cpp @@ -46,9 +46,20 @@ class BindingFabricTableDelegate : public chip::FabricTable::Delegate BindingFabricTableDelegate gFabricTableDelegate; -} // namespace +bool IsSelfNodeId(const chip::ScopedNodeId & nodeId) +{ + chip::FabricTable & fabricTable = chip::Server::GetInstance().GetFabricTable(); + for (const chip::FabricInfo & fabricInfo : fabricTable) + { + if (fabricInfo.GetScopedNodeId() == nodeId) + { + return true; + } + } + return false; +} -namespace {} // namespace +} // namespace namespace chip { @@ -189,10 +200,17 @@ CHIP_ERROR BindingManager::NotifyBoundClusterChanged(EndpointId endpoint, Cluste { if (iter->type == MATTER_UNICAST_BINDING) { - error = mPendingNotificationMap.AddPendingNotification(iter.GetIndex(), bindingContext); - SuccessOrExit(error); - error = EstablishConnection(ScopedNodeId(iter->nodeId, iter->fabricIndex)); - SuccessOrExit(error); + if (IsSelfNodeId(ScopedNodeId(iter->fabricIndex, iter->nodeId))) + { + mBoundDeviceChangedHandler(*iter, nullptr, bindingContext->GetContext()); + } + else + { + error = mPendingNotificationMap.AddPendingNotification(iter.GetIndex(), bindingContext); + SuccessOrExit(error); + error = EstablishConnection(ScopedNodeId(iter->nodeId, iter->fabricIndex)); + SuccessOrExit(error); + } } else if (iter->type == MATTER_MULTICAST_BINDING) { diff --git a/src/app/clusters/bindings/BindingManager.h b/src/app/clusters/bindings/BindingManager.h index c5828b42ac30a6..a992ec21a16e58 100644 --- a/src/app/clusters/bindings/BindingManager.h +++ b/src/app/clusters/bindings/BindingManager.h @@ -32,7 +32,8 @@ namespace chip { * The connection is managed by the stack and peer_device is guaranteed to be available. * The application shall decide the content to be sent to the peer. * - * For unicast bindings peer_device will be a connected peer and group will be empty. + * For unicast bindings to other devices, peer_device will be a connected peer. + * For unicast bindings to self, peer_device will be nullptr. * For multicast bindings peer_device will be nullptr. * * E.g. The application will send on/off commands to peer for the OnOff cluster. diff --git a/src/inet/UDPEndPointImplLwIP.cpp b/src/inet/UDPEndPointImplLwIP.cpp index 9d0d3bb396f482..35b8e9b4bbc4b7 100755 --- a/src/inet/UDPEndPointImplLwIP.cpp +++ b/src/inet/UDPEndPointImplLwIP.cpp @@ -129,6 +129,7 @@ uint16_t UDPEndPointImplLwIP::GetBoundPort() const CHIP_ERROR UDPEndPointImplLwIP::ListenImpl() { + mLwIPEndPointType = LwIPEndPointType::UDP; RunOnTCPIP([this]() { udp_recv(mUDP, LwIPReceiveUDPMessage, this); }); return CHIP_NO_ERROR; } @@ -420,11 +421,11 @@ CHIP_ERROR UDPEndPointImplLwIP::SetMulticastLoopback(IPVersion aIPVersion, bool { if (aLoopback) { - udp_set_flags(mUDP, UDP_FLAGS_MULTICAST_LOOP); + RunOnTCPIP([this]() { udp_set_flags(mUDP, UDP_FLAGS_MULTICAST_LOOP); }); } else { - udp_clear_flags(mUDP, UDP_FLAGS_MULTICAST_LOOP); + RunOnTCPIP([this]() { udp_clear_flags(mUDP, UDP_FLAGS_MULTICAST_LOOP); }); } return CHIP_NO_ERROR; } diff --git a/src/transport/raw/UDP.cpp b/src/transport/raw/UDP.cpp index 3113e9797bfc72..10d6b6832fc3bd 100644 --- a/src/transport/raw/UDP.cpp +++ b/src/transport/raw/UDP.cpp @@ -145,6 +145,17 @@ CHIP_ERROR UDP::MulticastGroupJoinLeave(const Transport::PeerAddress & address, if (join) { +#if INET_CONFIG_ENABLE_IPV4 + if (mUDPEndPoint->SetMulticastLoopback(address.GetIPAddress().IsIPv4() ? Inet::kIPVersion_4 : Inet::kIPVersion_6, true) != + CHIP_NO_ERROR) +#else + if (mUDPEndPoint->SetMulticastLoopback(Inet::kIPVersion_6, true) != CHIP_NO_ERROR) +#endif + { + ChipLogError(Inet, + "Failed to set multicast loop back, this could lead to that the device cannot receive multicast message " + "sent by itself"); + } ChipLogProgress(Inet, "Joining Multicast Group with address %s", addressStr); return mUDPEndPoint->JoinMulticastGroup(mUDPEndPoint->GetBoundInterface(), address.GetIPAddress()); }