Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
Kevin Schoedel | 1b6a96b | 2021-02-10 14:29:33 -0500 | [diff] [blame] | 3 | * Copyright (c) 2020-2021 Project CHIP Authors |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | */ |
| 17 | |
| 18 | /** |
| 19 | * @file |
| 20 | * This file implements the ExchangeManager class. |
| 21 | * |
| 22 | */ |
| 23 | |
Song Guo | 308b2a4 | 2020-10-28 14:25:49 +0800 | [diff] [blame] | 24 | #include <cstring> |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 25 | #include <inttypes.h> |
| 26 | #include <stddef.h> |
| 27 | |
Tennessee Carmel-Veilleux | 267951c | 2021-10-13 22:05:45 -0400 | [diff] [blame] | 28 | #include <crypto/RandUtils.h> |
Zang MingJie | 53dd583 | 2021-09-03 03:05:16 +0800 | [diff] [blame] | 29 | #include <lib/core/CHIPCore.h> |
| 30 | #include <lib/core/CHIPEncoding.h> |
| 31 | #include <lib/support/CHIPFaultInjection.h> |
| 32 | #include <lib/support/CodeUtils.h> |
Zang MingJie | 53dd583 | 2021-09-03 03:05:16 +0800 | [diff] [blame] | 33 | #include <lib/support/logging/CHIPLogging.h> |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 34 | #include <messaging/ExchangeContext.h> |
| 35 | #include <messaging/ExchangeMgr.h> |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 36 | #include <protocols/Protocols.h> |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 37 | |
| 38 | using namespace chip::Encoding; |
| 39 | using namespace chip::Inet; |
| 40 | using namespace chip::System; |
| 41 | |
| 42 | namespace chip { |
Yufeng Wang | 01031e7 | 2020-12-01 09:57:42 -0800 | [diff] [blame] | 43 | namespace Messaging { |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 44 | |
| 45 | /** |
| 46 | * Constructor for the ExchangeManager class. |
| 47 | * It sets the state to kState_NotInitialized. |
| 48 | * |
| 49 | * @note |
| 50 | * The class must be initialized via ExchangeManager::Init() |
| 51 | * prior to use. |
| 52 | * |
| 53 | */ |
Zang MingJie | 6c9f1c5 | 2021-11-18 00:58:13 +0800 | [diff] [blame] | 54 | ExchangeManager::ExchangeManager() : mReliableMessageMgr(mContextPool) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 55 | { |
| 56 | mState = State::kState_NotInitialized; |
| 57 | } |
| 58 | |
Zang MingJie | eca9bff | 2021-09-23 03:19:51 +0800 | [diff] [blame] | 59 | CHIP_ERROR ExchangeManager::Init(SessionManager * sessionManager) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 60 | { |
Yufeng Wang | a949773 | 2021-02-17 10:10:50 -0800 | [diff] [blame] | 61 | CHIP_ERROR err = CHIP_NO_ERROR; |
| 62 | |
| 63 | VerifyOrReturnError(mState == State::kState_NotInitialized, err = CHIP_ERROR_INCORRECT_STATE); |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 64 | |
Zang MingJie | eca9bff | 2021-09-23 03:19:51 +0800 | [diff] [blame] | 65 | mSessionManager = sessionManager; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 66 | |
Tennessee Carmel-Veilleux | 267951c | 2021-10-13 22:05:45 -0400 | [diff] [blame] | 67 | mNextExchangeId = chip::Crypto::GetRandU16(); |
Zang MingJie | a0db449 | 2021-03-10 01:00:35 +0800 | [diff] [blame] | 68 | mNextKeyId = 0; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 69 | |
Damian Królik | 36dd75b | 2021-03-23 15:34:38 +0100 | [diff] [blame] | 70 | for (auto & handler : UMHandlerPool) |
| 71 | { |
Boris Zbarsky | 01ce6aa | 2021-03-23 14:15:36 -0400 | [diff] [blame] | 72 | // Mark all handlers as unallocated. This handles both initial |
| 73 | // initialization and the case when the consumer shuts us down and |
| 74 | // then re-initializes without removing registered handlers. |
Boris Zbarsky | b8054db | 2021-03-25 14:46:17 -0400 | [diff] [blame] | 75 | handler.Reset(); |
Damian Królik | 36dd75b | 2021-03-23 15:34:38 +0100 | [diff] [blame] | 76 | } |
Zang MingJie | a0db449 | 2021-03-10 01:00:35 +0800 | [diff] [blame] | 77 | |
Zang MingJie | 6c9f1c5 | 2021-11-18 00:58:13 +0800 | [diff] [blame] | 78 | sessionManager->SetMessageDelegate(this); |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 79 | |
Zang MingJie | 4ec0e4e | 2021-12-02 15:20:06 +0800 | [diff] [blame] | 80 | mReliableMessageMgr.Init(sessionManager->SystemLayer()); |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 81 | |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 82 | mState = State::kState_Initialized; |
| 83 | |
Yufeng Wang | a949773 | 2021-02-17 10:10:50 -0800 | [diff] [blame] | 84 | return err; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 85 | } |
| 86 | |
Michael Spang | 6387049 | 2022-06-28 08:41:08 -0400 | [diff] [blame] | 87 | void ExchangeManager::Shutdown() |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 88 | { |
Michael Spang | 6387049 | 2022-06-28 08:41:08 -0400 | [diff] [blame] | 89 | VerifyOrReturn(mState != State::kState_NotInitialized); |
Vivien Nicolas | 862f170 | 2022-02-16 15:45:16 +0100 | [diff] [blame] | 90 | |
Kevin Schoedel | 1b6a96b | 2021-02-10 14:29:33 -0500 | [diff] [blame] | 91 | mReliableMessageMgr.Shutdown(); |
| 92 | |
Zang MingJie | eca9bff | 2021-09-23 03:19:51 +0800 | [diff] [blame] | 93 | if (mSessionManager != nullptr) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 94 | { |
Zang MingJie | 6c9f1c5 | 2021-11-18 00:58:13 +0800 | [diff] [blame] | 95 | mSessionManager->SetMessageDelegate(nullptr); |
Zang MingJie | eca9bff | 2021-09-23 03:19:51 +0800 | [diff] [blame] | 96 | mSessionManager = nullptr; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 97 | } |
| 98 | |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 99 | mState = State::kState_NotInitialized; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 100 | } |
| 101 | |
Jerry Johns | 55f9049 | 2022-08-29 01:14:05 -0400 | [diff] [blame] | 102 | ExchangeContext * ExchangeManager::NewContext(const SessionHandle & session, ExchangeDelegate * delegate, bool isInitiator) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 103 | { |
Zang MingJie | 7d125dc | 2022-06-09 00:11:05 +0800 | [diff] [blame] | 104 | if (!session->IsActiveSession()) |
| 105 | { |
| 106 | // Disallow creating exchange on an inactive session |
| 107 | ChipLogError(ExchangeManager, "NewContext failed: session inactive"); |
| 108 | return nullptr; |
| 109 | } |
Jerry Johns | 55f9049 | 2022-08-29 01:14:05 -0400 | [diff] [blame] | 110 | return mContextPool.CreateObject(this, mNextExchangeId++, session, isInitiator, delegate); |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 111 | } |
| 112 | |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 113 | CHIP_ERROR ExchangeManager::RegisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId, |
| 114 | UnsolicitedMessageHandler * handler) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 115 | { |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 116 | return RegisterUMH(protocolId, kAnyMessageType, handler); |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 117 | } |
| 118 | |
Boris Zbarsky | f0b7f2b | 2021-03-22 12:32:13 -0400 | [diff] [blame] | 119 | CHIP_ERROR ExchangeManager::RegisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType, |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 120 | UnsolicitedMessageHandler * handler) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 121 | { |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 122 | return RegisterUMH(protocolId, static_cast<int16_t>(msgType), handler); |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 123 | } |
| 124 | |
Boris Zbarsky | f0b7f2b | 2021-03-22 12:32:13 -0400 | [diff] [blame] | 125 | CHIP_ERROR ExchangeManager::UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::Id protocolId) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 126 | { |
| 127 | return UnregisterUMH(protocolId, kAnyMessageType); |
| 128 | } |
| 129 | |
Boris Zbarsky | f0b7f2b | 2021-03-22 12:32:13 -0400 | [diff] [blame] | 130 | CHIP_ERROR ExchangeManager::UnregisterUnsolicitedMessageHandlerForType(Protocols::Id protocolId, uint8_t msgType) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 131 | { |
| 132 | return UnregisterUMH(protocolId, static_cast<int16_t>(msgType)); |
| 133 | } |
| 134 | |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 135 | CHIP_ERROR ExchangeManager::RegisterUMH(Protocols::Id protocolId, int16_t msgType, UnsolicitedMessageHandler * handler) |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 136 | { |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 137 | UnsolicitedMessageHandlerSlot * selected = nullptr; |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 138 | |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 139 | for (auto & umh : UMHandlerPool) |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 140 | { |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 141 | if (!umh.IsInUse()) |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 142 | { |
| 143 | if (selected == nullptr) |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 144 | selected = &umh; |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 145 | } |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 146 | else if (umh.Matches(protocolId, msgType)) |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 147 | { |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 148 | umh.Handler = handler; |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 149 | return CHIP_NO_ERROR; |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | if (selected == nullptr) |
| 154 | return CHIP_ERROR_TOO_MANY_UNSOLICITED_MESSAGE_HANDLERS; |
| 155 | |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 156 | selected->Handler = handler; |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 157 | selected->ProtocolId = protocolId; |
| 158 | selected->MessageType = msgType; |
| 159 | |
| 160 | SYSTEM_STATS_INCREMENT(chip::System::Stats::kExchangeMgr_NumUMHandlers); |
| 161 | |
| 162 | return CHIP_NO_ERROR; |
| 163 | } |
| 164 | |
Boris Zbarsky | f0b7f2b | 2021-03-22 12:32:13 -0400 | [diff] [blame] | 165 | CHIP_ERROR ExchangeManager::UnregisterUMH(Protocols::Id protocolId, int16_t msgType) |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 166 | { |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 167 | for (auto & umh : UMHandlerPool) |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 168 | { |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 169 | if (umh.IsInUse() && umh.Matches(protocolId, msgType)) |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 170 | { |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 171 | umh.Reset(); |
Zang MingJie | 8458652 | 2021-01-27 02:05:37 +0800 | [diff] [blame] | 172 | SYSTEM_STATS_DECREMENT(chip::System::Stats::kExchangeMgr_NumUMHandlers); |
| 173 | return CHIP_NO_ERROR; |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | return CHIP_ERROR_NO_UNSOLICITED_MESSAGE_HANDLER; |
| 178 | } |
| 179 | |
| 180 | void ExchangeManager::OnMessageReceived(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, |
Zang MingJie | 40842bf | 2022-04-22 00:28:36 +0800 | [diff] [blame] | 181 | const SessionHandle & session, DuplicateMessage isDuplicate, |
| 182 | System::PacketBufferHandle && msgBuf) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 183 | { |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 184 | UnsolicitedMessageHandlerSlot * matchingUMH = nullptr; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 185 | |
Jerry Johns | 9441289 | 2022-09-13 16:33:36 -0400 | [diff] [blame] | 186 | #if CHIP_PROGRESS_LOGGING |
| 187 | auto * protocolName = Protocols::GetProtocolName(payloadHeader.GetProtocolID()); |
| 188 | auto * msgTypeName = Protocols::GetMessageTypeName(payloadHeader.GetProtocolID(), payloadHeader.GetMessageType()); |
| 189 | |
| 190 | // |
| 191 | // 32-bit value maximum = 10 chars + text preamble (6) + trailer (1) + null (1) + 2 buffer = 20 |
| 192 | // |
| 193 | char ackBuf[20]; |
| 194 | ackBuf[0] = '\0'; |
| 195 | if (payloadHeader.GetAckMessageCounter().HasValue()) |
| 196 | { |
| 197 | snprintf(ackBuf, sizeof(ackBuf), " (Ack:" ChipLogFormatMessageCounter ")", payloadHeader.GetAckMessageCounter().Value()); |
| 198 | } |
| 199 | |
| 200 | CompressedFabricId compressedFabricId = 0; |
| 201 | if (session->IsSecureSession() && mSessionManager->GetFabricTable() != nullptr) |
| 202 | { |
| 203 | auto fabricInfo = mSessionManager->GetFabricTable()->FindFabricWithIndex(session->AsSecureSession()->GetFabricIndex()); |
| 204 | if (fabricInfo) |
| 205 | { |
| 206 | compressedFabricId = fabricInfo->GetCompressedFabricId(); |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | // |
| 211 | // Legend that can be used to decode this log line can be found in README.md |
| 212 | // |
Boris Zbarsky | f7c5127 | 2021-09-22 10:22:31 -0400 | [diff] [blame] | 213 | ChipLogProgress(ExchangeManager, |
Boris Zbarsky | c77dbde | 2023-02-08 11:00:38 -0500 | [diff] [blame] | 214 | ">>> [E:" ChipLogFormatExchangeId " S:%u M:" ChipLogFormatMessageCounter |
| 215 | "%s] (%s) Msg RX from %u:" ChipLogFormatX64 " [%04X] --- Type %04x:%02x (%s:%s)", |
| 216 | ChipLogValueExchangeIdFromReceivedHeader(payloadHeader), session->SessionIdForLogging(), |
| 217 | packetHeader.GetMessageCounter(), ackBuf, Transport::GetSessionTypeString(session), session->GetFabricIndex(), |
Jerry Johns | 9441289 | 2022-09-13 16:33:36 -0400 | [diff] [blame] | 218 | ChipLogValueX64(session->GetPeer().GetNodeId()), static_cast<uint16_t>(compressedFabricId), |
| 219 | payloadHeader.GetProtocolID().GetProtocolId(), payloadHeader.GetMessageType(), protocolName, msgTypeName); |
| 220 | #endif |
shana-apple | 3907f38 | 2021-05-05 08:50:42 +0200 | [diff] [blame] | 221 | |
Pankaj Garg | 48ed12b | 2021-06-28 10:07:30 -0700 | [diff] [blame] | 222 | MessageFlags msgFlags; |
| 223 | if (isDuplicate == DuplicateMessage::Yes) |
| 224 | { |
| 225 | msgFlags.Set(MessageFlagValues::kDuplicateMessage); |
| 226 | } |
| 227 | |
jepenven-silabs | fb1a62e | 2021-11-05 13:51:12 -0400 | [diff] [blame] | 228 | // Skip retrieval of exchange for group message since no exchange is stored |
| 229 | // for group msg (optimization) |
| 230 | if (!packetHeader.IsGroupSession()) |
Zang MingJie | 1b5d2a7 | 2021-05-15 04:13:32 +0800 | [diff] [blame] | 231 | { |
jepenven-silabs | fb1a62e | 2021-11-05 13:51:12 -0400 | [diff] [blame] | 232 | // Search for an existing exchange that the message applies to. If a match is found... |
| 233 | bool found = false; |
| 234 | mContextPool.ForEachActiveObject([&](auto * ec) { |
| 235 | if (ec->MatchExchange(session, packetHeader, payloadHeader)) |
| 236 | { |
Boris Zbarsky | 1ad526b | 2021-12-02 19:31:01 -0500 | [diff] [blame] | 237 | ChipLogDetail(ExchangeManager, "Found matching exchange: " ChipLogFormatExchange ", Delegate: %p", |
Boris Zbarsky | ffee2a9 | 2021-12-01 14:34:57 -0500 | [diff] [blame] | 238 | ChipLogValueExchange(ec), ec->GetDelegate()); |
| 239 | |
jepenven-silabs | fb1a62e | 2021-11-05 13:51:12 -0400 | [diff] [blame] | 240 | // Matched ExchangeContext; send to message handler. |
Zang MingJie | 40842bf | 2022-04-22 00:28:36 +0800 | [diff] [blame] | 241 | ec->HandleMessage(packetHeader.GetMessageCounter(), payloadHeader, msgFlags, std::move(msgBuf)); |
jepenven-silabs | fb1a62e | 2021-11-05 13:51:12 -0400 | [diff] [blame] | 242 | found = true; |
Zang MingJie | e2e4c17 | 2021-12-03 01:15:02 +0800 | [diff] [blame] | 243 | return Loop::Break; |
jepenven-silabs | fb1a62e | 2021-11-05 13:51:12 -0400 | [diff] [blame] | 244 | } |
Zang MingJie | e2e4c17 | 2021-12-03 01:15:02 +0800 | [diff] [blame] | 245 | return Loop::Continue; |
jepenven-silabs | fb1a62e | 2021-11-05 13:51:12 -0400 | [diff] [blame] | 246 | }); |
| 247 | |
| 248 | if (found) |
| 249 | { |
| 250 | return; |
| 251 | } |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 252 | } |
Jean-Francois Penven | ae485d1 | 2021-12-07 10:41:05 -0500 | [diff] [blame] | 253 | else |
| 254 | { |
Jerry Johns | 9441289 | 2022-09-13 16:33:36 -0400 | [diff] [blame] | 255 | ChipLogProgress(ExchangeManager, "Received Groupcast Message with GroupId 0x%04X (%d)", |
| 256 | packetHeader.GetDestinationGroupId().Value(), packetHeader.GetDestinationGroupId().Value()); |
Jean-Francois Penven | ae485d1 | 2021-12-07 10:41:05 -0500 | [diff] [blame] | 257 | } |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 258 | |
Boris Zbarsky | 03de700 | 2022-06-22 19:19:30 -0400 | [diff] [blame] | 259 | // Do not handle messages that don't match an existing exchange on an |
| 260 | // inactive session, since we should not be creating new exchanges there. |
| 261 | if (!session->IsActiveSession()) |
| 262 | { |
| 263 | ChipLogProgress(ExchangeManager, "Dropping message on inactive session that does not match an existing exchange"); |
| 264 | return; |
| 265 | } |
| 266 | |
Pankaj Garg | 48ed12b | 2021-06-28 10:07:30 -0700 | [diff] [blame] | 267 | // If it's not a duplicate message, search for an unsolicited message handler if it is marked as being sent by an initiator. |
| 268 | // Since we didn't find an existing exchange that matches the message, it must be an unsolicited message. However all |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 269 | // unsolicited messages must be marked as being from an initiator. |
Jerry Johns | c6724a0 | 2022-06-21 06:47:02 -0700 | [diff] [blame] | 270 | if (!msgFlags.Has(MessageFlagValues::kDuplicateMessage) && payloadHeader.IsInitiator()) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 271 | { |
| 272 | // Search for an unsolicited message handler that can handle the message. Prefer handlers that can explicitly |
| 273 | // handle the message type over handlers that handle all messages for a profile. |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 274 | matchingUMH = nullptr; |
| 275 | |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 276 | for (auto & umh : UMHandlerPool) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 277 | { |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 278 | if (umh.IsInUse() && payloadHeader.HasProtocol(umh.ProtocolId)) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 279 | { |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 280 | if (umh.MessageType == payloadHeader.GetMessageType()) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 281 | { |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 282 | matchingUMH = &umh; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 283 | break; |
| 284 | } |
| 285 | |
Boris Zbarsky | d87cdb7 | 2021-05-20 10:41:42 -0400 | [diff] [blame] | 286 | if (umh.MessageType == kAnyMessageType) |
| 287 | matchingUMH = &umh; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 288 | } |
| 289 | } |
| 290 | } |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 291 | // Discard the message if it isn't marked as being sent by an initiator and the message does not need to send |
| 292 | // an ack to the peer. |
Yufeng Wang | 3d79e0e | 2021-02-09 12:04:30 -0800 | [diff] [blame] | 293 | else if (!payloadHeader.NeedsAck()) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 294 | { |
Boris Zbarsky | ef5bda7 | 2023-09-15 13:07:38 -0400 | [diff] [blame] | 295 | // We can easily get standalone acks here: any time we fail to get a |
| 296 | // timely ack for the last message in an exchange and retransmit it, |
| 297 | // then get acks for both the message and the retransmit, the second ack |
| 298 | // will end up in this block. That's not really an error condition, so |
| 299 | // there is no need to log an error in that case. |
| 300 | if (!payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::StandaloneAck)) |
| 301 | { |
| 302 | // Using same error message for all errors to reduce code size. |
| 303 | ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, |
| 304 | CHIP_ERROR_UNSOLICITED_MSG_NO_ORIGINATOR.Format()); |
| 305 | } |
Zang MingJie | 32c1393 | 2021-07-20 22:18:50 +0800 | [diff] [blame] | 306 | return; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 307 | } |
| 308 | |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 309 | // If we found a handler, create an exchange to handle the message. |
| 310 | if (matchingUMH != nullptr) |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 311 | { |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 312 | ExchangeDelegate * delegate = nullptr; |
| 313 | |
| 314 | // Fetch delegate from the handler |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 315 | CHIP_ERROR err = matchingUMH->Handler->OnUnsolicitedMessageReceived(payloadHeader, delegate); |
| 316 | if (err != CHIP_NO_ERROR) |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 317 | { |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 318 | // Using same error message for all errors to reduce code size. |
Damian Królik | 5e9d413 | 2022-06-27 09:02:15 +0200 | [diff] [blame] | 319 | ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, err.Format()); |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 320 | SendStandaloneAckIfNeeded(packetHeader, payloadHeader, session, msgFlags, std::move(msgBuf)); |
| 321 | return; |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 322 | } |
| 323 | |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 324 | ExchangeContext * ec = mContextPool.CreateObject(this, payloadHeader.GetExchangeID(), session, false, delegate); |
Yufeng Wang | cb23e0c | 2021-01-07 12:36:21 -0800 | [diff] [blame] | 325 | |
Zang MingJie | 32c1393 | 2021-07-20 22:18:50 +0800 | [diff] [blame] | 326 | if (ec == nullptr) |
| 327 | { |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 328 | if (delegate != nullptr) |
Zang MingJie | d1512e5 | 2022-04-15 12:26:24 +0800 | [diff] [blame] | 329 | { |
| 330 | matchingUMH->Handler->OnExchangeCreationFailed(delegate); |
| 331 | } |
| 332 | |
Zang MingJie | 32c1393 | 2021-07-20 22:18:50 +0800 | [diff] [blame] | 333 | // Using same error message for all errors to reduce code size. |
Damian Królik | 5e9d413 | 2022-06-27 09:02:15 +0200 | [diff] [blame] | 334 | ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, CHIP_ERROR_NO_MEMORY.Format()); |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 335 | // No resource for creating new exchange, SendStandaloneAckIfNeeded probably also fails, so do not try it here |
Zang MingJie | 32c1393 | 2021-07-20 22:18:50 +0800 | [diff] [blame] | 336 | return; |
| 337 | } |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 338 | |
Boris Zbarsky | 1ad526b | 2021-12-02 19:31:01 -0500 | [diff] [blame] | 339 | ChipLogDetail(ExchangeManager, "Handling via exchange: " ChipLogFormatExchange ", Delegate: %p", ChipLogValueExchange(ec), |
Boris Zbarsky | dbbe48d | 2021-09-21 16:06:03 -0400 | [diff] [blame] | 340 | ec->GetDelegate()); |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 341 | |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 342 | if (ec->IsEncryptionRequired() != packetHeader.IsEncrypted()) |
Zang MingJie | 2b2622f | 2021-09-10 20:59:20 +0800 | [diff] [blame] | 343 | { |
Damian Królik | 5e9d413 | 2022-06-27 09:02:15 +0200 | [diff] [blame] | 344 | ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, |
| 345 | CHIP_ERROR_INVALID_MESSAGE_TYPE.Format()); |
Zang MingJie | 2b2622f | 2021-09-10 20:59:20 +0800 | [diff] [blame] | 346 | ec->Close(); |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 347 | SendStandaloneAckIfNeeded(packetHeader, payloadHeader, session, msgFlags, std::move(msgBuf)); |
| 348 | return; |
Zang MingJie | 2b2622f | 2021-09-10 20:59:20 +0800 | [diff] [blame] | 349 | } |
| 350 | |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 351 | err = ec->HandleMessage(packetHeader.GetMessageCounter(), payloadHeader, msgFlags, std::move(msgBuf)); |
Trevor Holbrook | 8c419b6 | 2021-07-30 07:43:45 -0700 | [diff] [blame] | 352 | if (err != CHIP_NO_ERROR) |
| 353 | { |
| 354 | // Using same error message for all errors to reduce code size. |
Damian Królik | 5e9d413 | 2022-06-27 09:02:15 +0200 | [diff] [blame] | 355 | ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, err.Format()); |
Trevor Holbrook | 8c419b6 | 2021-07-30 07:43:45 -0700 | [diff] [blame] | 356 | } |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 357 | return; |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 358 | } |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 359 | |
| 360 | SendStandaloneAckIfNeeded(packetHeader, payloadHeader, session, msgFlags, std::move(msgBuf)); |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 361 | } |
| 362 | |
| 363 | void ExchangeManager::SendStandaloneAckIfNeeded(const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, |
| 364 | const SessionHandle & session, MessageFlags msgFlags, |
| 365 | System::PacketBufferHandle && msgBuf) |
| 366 | { |
Pradip De | d82ce57 | 2023-11-24 12:22:18 -0800 | [diff] [blame] | 367 | |
| 368 | // If using the MRP protocol and we need to send a StandaloneAck, create an EphemeralExchange to send |
| 369 | // the StandaloneAck. |
| 370 | if (!session->AllowsMRP() || !payloadHeader.NeedsAck()) |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 371 | return; |
| 372 | |
| 373 | // If rcvd msg is from initiator then this exchange is created as not Initiator. |
| 374 | // If rcvd msg is not from initiator then this exchange is created as Initiator. |
| 375 | // Create a EphemeralExchange to generate a StandaloneAck |
| 376 | ExchangeContext * ec = mContextPool.CreateObject(this, payloadHeader.GetExchangeID(), session, !payloadHeader.IsInitiator(), |
| 377 | nullptr, true /* IsEphemeralExchange */); |
| 378 | |
| 379 | if (ec == nullptr) |
| 380 | { |
| 381 | // Using same error message for all errors to reduce code size. |
Damian Królik | 5e9d413 | 2022-06-27 09:02:15 +0200 | [diff] [blame] | 382 | ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, CHIP_ERROR_NO_MEMORY.Format()); |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 383 | return; |
| 384 | } |
| 385 | |
| 386 | ChipLogDetail(ExchangeManager, "Generating StandaloneAck via exchange: " ChipLogFormatExchange, ChipLogValueExchange(ec)); |
| 387 | |
| 388 | // No need to verify packet encryption type, the EphemeralExchange can handle both secure and insecure messages. |
| 389 | |
| 390 | CHIP_ERROR err = ec->HandleMessage(packetHeader.GetMessageCounter(), payloadHeader, msgFlags, std::move(msgBuf)); |
| 391 | if (err != CHIP_NO_ERROR) |
| 392 | { |
| 393 | // Using same error message for all errors to reduce code size. |
Damian Królik | 5e9d413 | 2022-06-27 09:02:15 +0200 | [diff] [blame] | 394 | ChipLogError(ExchangeManager, "OnMessageReceived failed, err = %" CHIP_ERROR_FORMAT, err.Format()); |
Zang MingJie | d2a2f07 | 2022-06-10 22:09:05 +0800 | [diff] [blame] | 395 | } |
| 396 | |
| 397 | // The exchange should be closed inside HandleMessage function. So don't bother close it here. |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 398 | } |
| 399 | |
Pankaj Garg | 107a380 | 2021-05-25 09:48:45 -0700 | [diff] [blame] | 400 | void ExchangeManager::CloseAllContextsForDelegate(const ExchangeDelegate * delegate) |
Boris Zbarsky | 0fe16aa | 2021-05-05 17:02:54 -0400 | [diff] [blame] | 401 | { |
Zang MingJie | 1b5d2a7 | 2021-05-15 04:13:32 +0800 | [diff] [blame] | 402 | mContextPool.ForEachActiveObject([&](auto * ec) { |
| 403 | if (ec->GetDelegate() == delegate) |
Boris Zbarsky | 0fe16aa | 2021-05-05 17:02:54 -0400 | [diff] [blame] | 404 | { |
Zang MingJie | 1b5d2a7 | 2021-05-15 04:13:32 +0800 | [diff] [blame] | 405 | // Make sure to null out the delegate before closing the context, so |
| 406 | // we don't notify the delegate that the context is closing. We |
| 407 | // have to do this, because the delegate might be partially |
| 408 | // destroyed by this point. |
| 409 | ec->SetDelegate(nullptr); |
| 410 | ec->Close(); |
Boris Zbarsky | 0fe16aa | 2021-05-05 17:02:54 -0400 | [diff] [blame] | 411 | } |
Zang MingJie | e2e4c17 | 2021-12-03 01:15:02 +0800 | [diff] [blame] | 412 | return Loop::Continue; |
Zang MingJie | 1b5d2a7 | 2021-05-15 04:13:32 +0800 | [diff] [blame] | 413 | }); |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 414 | } |
| 415 | |
Yufeng Wang | 01031e7 | 2020-12-01 09:57:42 -0800 | [diff] [blame] | 416 | } // namespace Messaging |
Yufeng Wang | 4fc19f1 | 2020-10-22 16:14:32 -0700 | [diff] [blame] | 417 | } // namespace chip |