/* * * 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 provides implementation of ExchangeMessageDispatch class. */ #include #include #include #include #include #include #include #include namespace chip { namespace Messaging { CHIP_ERROR ExchangeMessageDispatch::SendMessage(SessionManager * sessionManager, const SessionHandle & session, uint16_t exchangeId, bool isInitiator, ReliableMessageContext * reliableMessageContext, bool isReliableTransmission, Protocols::Id protocol, uint8_t type, System::PacketBufferHandle && message) { VerifyOrReturnError(MessagePermitted(protocol, type), CHIP_ERROR_INVALID_ARGUMENT); PayloadHeader payloadHeader; payloadHeader.SetExchangeID(exchangeId).SetMessageType(protocol, type).SetInitiator(isInitiator); if (session->AllowsMRP()) { // If there is a pending acknowledgment piggyback it on this message. if (reliableMessageContext->HasPiggybackAckPending()) { payloadHeader.SetAckMessageCounter(reliableMessageContext->TakePendingPeerAckMessageCounter()); } if (IsReliableTransmissionAllowed() && reliableMessageContext->AutoRequestAck() && reliableMessageContext->GetReliableMessageMgr() != nullptr && isReliableTransmission) { auto * reliableMessageMgr = reliableMessageContext->GetReliableMessageMgr(); payloadHeader.SetNeedsAck(true); ReliableMessageMgr::RetransTableEntry * entry = nullptr; // Add to Table for subsequent sending ReturnErrorOnFailure(reliableMessageMgr->AddToRetransTable(reliableMessageContext, &entry)); auto deleter = [reliableMessageMgr](ReliableMessageMgr::RetransTableEntry * e) { reliableMessageMgr->ClearRetransTable(*e); }; std::unique_ptr entryOwner(entry, deleter); ReturnErrorOnFailure( sessionManager->PrepareMessage(session, payloadHeader, std::move(message), entryOwner->retainedBuf)); CHIP_ERROR err = sessionManager->SendPreparedMessage(session, entryOwner->retainedBuf); err = ReliableMessageMgr::MapSendError(err, exchangeId, isInitiator); ReturnErrorOnFailure(err); reliableMessageMgr->StartRetransmision(entryOwner.release()); } else { ReturnErrorOnFailure(PrepareAndSendNonMRPMessage(sessionManager, session, payloadHeader, std::move(message))); } } else { ReturnErrorOnFailure(PrepareAndSendNonMRPMessage(sessionManager, session, payloadHeader, std::move(message))); } return CHIP_NO_ERROR; } CHIP_ERROR ExchangeMessageDispatch::PrepareAndSendNonMRPMessage(SessionManager * sessionManager, const SessionHandle & session, PayloadHeader & payloadHeader, System::PacketBufferHandle && message) { payloadHeader.SetNeedsAck(false); EncryptedPacketBufferHandle preparedMessage; ReturnErrorOnFailure(sessionManager->PrepareMessage(session, payloadHeader, std::move(message), preparedMessage)); ReturnErrorOnFailure(sessionManager->SendPreparedMessage(session, preparedMessage)); return CHIP_NO_ERROR; } } // namespace Messaging } // namespace chip