diff --git a/src/messaging/ExchangeContext.cpp b/src/messaging/ExchangeContext.cpp index 9661f7020d4cdd..c5bb3bf02bcd94 100644 --- a/src/messaging/ExchangeContext.cpp +++ b/src/messaging/ExchangeContext.cpp @@ -254,7 +254,9 @@ ExchangeContext::ExchangeContext(ExchangeManager * em, uint16_t ExchangeId, Sess SetDropAckDebug(false); SetAckPending(false); SetMsgRcvdFromPeer(false); - SetAutoRequestAck(true); + + // Do not request Ack for multicast + SetAutoRequestAck(!session.GetGroupId().HasValue()); #if defined(CHIP_EXCHANGE_CONTEXT_DETAIL_LOGGING) ChipLogDetail(ExchangeManager, "ec++ id: " ChipLogFormatExchange, ChipLogValueExchange(this)); diff --git a/src/messaging/ExchangeMgr.cpp b/src/messaging/ExchangeMgr.cpp index 5d88c689ed7e50..20b730f30a8946 100644 --- a/src/messaging/ExchangeMgr.cpp +++ b/src/messaging/ExchangeMgr.cpp @@ -213,29 +213,33 @@ void ExchangeManager::OnMessageReceived(const PacketHeader & packetHeader, const msgFlags.Set(MessageFlagValues::kDuplicateMessage); } - // Search for an existing exchange that the message applies to. If a match is found... - bool found = false; - mContextPool.ForEachActiveObject([&](auto * ec) { - if (ec->MatchExchange(session, packetHeader, payloadHeader)) - { - // Found a matching exchange. Set flag for correct subsequent MRP - // retransmission timeout selection. - if (!ec->HasRcvdMsgFromPeer()) + // Skip retrieval of exchange for group message + if (!session.GetGroupId().HasValue()) + { + // Search for an existing exchange that the message applies to. If a match is found... + bool found = false; + mContextPool.ForEachActiveObject([&](auto * ec) { + if (ec->MatchExchange(session, packetHeader, payloadHeader)) { - ec->SetMsgRcvdFromPeer(true); + // Found a matching exchange. Set flag for correct subsequent MRP + // retransmission timeout selection. + if (!ec->HasRcvdMsgFromPeer()) + { + ec->SetMsgRcvdFromPeer(true); + } + + // Matched ExchangeContext; send to message handler. + ec->HandleMessage(packetHeader.GetMessageCounter(), payloadHeader, source, msgFlags, std::move(msgBuf)); + found = true; + return false; } + return true; + }); - // Matched ExchangeContext; send to message handler. - ec->HandleMessage(packetHeader.GetMessageCounter(), payloadHeader, source, msgFlags, std::move(msgBuf)); - found = true; - return false; + if (found) + { + return; } - return true; - }); - - if (found) - { - return; } // If it's not a duplicate message, search for an unsolicited message handler if it is marked as being sent by an initiator. @@ -273,7 +277,7 @@ void ExchangeManager::OnMessageReceived(const PacketHeader & packetHeader, const // If we found a handler or we need to send an ack, create an exchange to // handle the message. - if (matchingUMH != nullptr || payloadHeader.NeedsAck()) + if (matchingUMH != nullptr || payloadHeader.NeedsAck() || session.GetGroupId().HasValue()) { ExchangeDelegate * delegate = matchingUMH ? matchingUMH->Delegate : nullptr; // If rcvd msg is from initiator then this exchange is created as not Initiator. @@ -306,6 +310,12 @@ void ExchangeManager::OnMessageReceived(const PacketHeader & packetHeader, const // Using same error message for all errors to reduce code size. ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %s", ErrorStr(err)); } + + // close Exchange for group message + if (session.GetGroupId().HasValue()) + { + ec->Close(); + } } } diff --git a/src/transport/SessionHandle.h b/src/transport/SessionHandle.h index 0b738011af3469..844d7d0c75204e 100644 --- a/src/transport/SessionHandle.h +++ b/src/transport/SessionHandle.h @@ -43,6 +43,11 @@ class SessionHandle mPeerSessionId.SetValue(peerSessionId); } + SessionHandle(NodeId peerNodeId, GroupId groupId, FabricIndex fabric) : mPeerNodeId(peerNodeId), mFabric(fabric) + { + mGroupId.SetValue(groupId); + } + bool IsSecure() const { return !mUnauthenticatedSessionHandle.HasValue(); } bool HasFabricIndex() const { return (mFabric != kUndefinedFabricIndex); } @@ -70,6 +75,7 @@ class SessionHandle NodeId GetPeerNodeId() const { return mPeerNodeId; } const Optional & GetPeerSessionId() const { return mPeerSessionId; } const Optional & GetLocalSessionId() const { return mLocalSessionId; } + const Optional & GetGroupId() const { return mGroupId; } // Return the peer address for this session. May return null if the peer // address is not known. This can happen for secure sessions that have been @@ -85,6 +91,7 @@ class SessionHandle NodeId mPeerNodeId; Optional mLocalSessionId; Optional mPeerSessionId; + Optional mGroupId; // TODO: Re-evaluate the storing of Fabric ID in SessionHandle // The Fabric ID will not be available for PASE and group sessions. So need // to identify an approach that'll allow looking up the corresponding information for diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index 82ae6587bbb816..0fb575d20eee6f 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -459,16 +459,18 @@ void SessionManager::SecureGroupMessageDispatch(const PacketHeader & packetHeade CHIP_ERROR err = CHIP_NO_ERROR; PayloadHeader payloadHeader; SessionManagerDelegate::DuplicateMessage isDuplicate = SessionManagerDelegate::DuplicateMessage::No; + FabricIndex fabricIndex = 0; // TODO : remove initialization once GroupDataProvider->Decrypt is implemented // Credentials::GroupDataProvider * groups = Credentials::GetGroupDataProvider(); VerifyOrExit(!msg.IsNull(), ChipLogError(Inet, "Secure transport received NULL packet, discarding")); + VerifyOrExit(!payloadHeader.NeedsAck(), ChipLogError(Inet, "Group message received with ack request, discarding")); // MCSP check if (packetHeader.IsSecureSessionControlMsg()) { if (packetHeader.GetDestinationNodeId().HasValue() && packetHeader.HasPrivacyFlag()) { - // TODO + // TODO : Implement MCSP check. Issue #11076 // if (packetHeader.GetDestinationNodeId().Value() == ThisDeviceNodeID) // { // MCSP processing.. @@ -485,31 +487,28 @@ void SessionManager::SecureGroupMessageDispatch(const PacketHeader & packetHeade // spec 4.5.1.2 for msg counter // Trial decryption with GroupDataProvider. TODO: Implement the GroupDataProvider Class + // TODO retrieve also the fabricIndex with the GroupDataProvider. // VerifyOrExit(CHIP_NO_ERROR == groups->DecryptMessage(packetHeader, payloadHeader, msg), // ChipLogError(Inet, "Secure transport received group message, but failed to decode it, discarding")); - if (isDuplicate == SessionManagerDelegate::DuplicateMessage::Yes && !payloadHeader.NeedsAck()) + if (isDuplicate == SessionManagerDelegate::DuplicateMessage::Yes) { ChipLogDetail(Inet, "Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter " on exchange " ChipLogFormatExchangeId, - packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader)); - if (!payloadHeader.NeedsAck()) - { - // If it's a duplicate message, but doesn't require an ack, let's drop it right here to save CPU - // cycles on further message processing. - ExitNow(err = CHIP_NO_ERROR); - } + packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromSentHeader(payloadHeader)); + + // If it's a duplicate message, let's drop it right here to save CPU + // cycles on further message processing. + ExitNow(err = CHIP_NO_ERROR); } // TODO: Commit Group Message Counter if (mCB != nullptr) { - // TODO: Update Session Handle for Group messages. - // SessionHandle session(session->GetPeerNodeId(), session->GetLocalSessionId(), session->GetPeerSessionId(), - // session->GetFabricIndex()); - // mCB->OnMessageReceived(packetHeader, payloadHeader, session, peerAddress, isDuplicate, std::move(msg)); + SessionHandle session(packetHeader.GetSourceNodeId().Value(), packetHeader.GetDestinationGroupId().Value(), fabricIndex); + mCB->OnMessageReceived(packetHeader, payloadHeader, session, peerAddress, isDuplicate, std::move(msg)); } exit: