From 9d5539844cffdd6a030a7917496b41995ab82d87 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 18 May 2026 19:11:41 -0700 Subject: [PATCH] [ble] simplify `BleSecure::HandleTlsReceive()` (#13118) This commit simplifies the logic in `BleSecure::HandleTlsReceive` by reducing the nesting level through the use of early `ExitNow()` calls and replacing a complex `if-else` block with a `switch` statement for handling `errorTcatAgent`. Key improvements: - Removed a large `else` block by adding `ExitNow()` after the initial transparent mode check. - Used a `switch` statement to handle `errorTcatAgent` returned by `MeshCoP::TcatAgent::HandleSingleTlv()`, clearly separating `kErrorNone`, `kErrorAbort` (disconnect), and default fatal error handling. - Improved code formatting and comment readability. --- src/core/radio/ble_secure.cpp | 184 ++++++++++++++++++---------------- 1 file changed, 98 insertions(+), 86 deletions(-) diff --git a/src/core/radio/ble_secure.cpp b/src/core/radio/ble_secure.cpp index c02b220b1..7b739eb84 100644 --- a/src/core/radio/ble_secure.cpp +++ b/src/core/radio/ble_secure.cpp @@ -473,7 +473,10 @@ void BleSecure::HandleTlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength void BleSecure::HandleTlsReceive(uint8_t *aBuf, uint16_t aLength) { - otError error = kErrorNone; + Error error = kErrorNone; + Tlv tlv; + uint32_t requiredBytes; + uint32_t offset; VerifyOrExit(mReceivedMessage != nullptr); DumpDebg("Rx", aBuf, aLength); @@ -483,113 +486,122 @@ void BleSecure::HandleTlsReceive(uint8_t *aBuf, uint16_t aLength) SuccessOrExit(error = mReceivedMessage->AppendBytes(aBuf, aLength)); mReceiveCallback.InvokeIfSet(&GetInstance(), mReceivedMessage, 0, OT_TCAT_APPLICATION_PROTOCOL_NONE); IgnoreError(mReceivedMessage->SetLength(0)); + ExitNow(); } - else + + requiredBytes = sizeof(Tlv); + + while (aLength > 0) { - ot::Tlv tlv; - uint32_t requiredBytes = sizeof(Tlv); - uint32_t offset; - - while (aLength > 0) + if (mReceivedMessage->GetLength() < requiredBytes) { - if (mReceivedMessage->GetLength() < requiredBytes) - { - uint32_t missingBytes = requiredBytes - mReceivedMessage->GetLength(); + uint32_t missingBytes = requiredBytes - mReceivedMessage->GetLength(); - if (missingBytes > aLength) - { - SuccessOrExit(error = mReceivedMessage->AppendBytes(aBuf, aLength)); - break; - } - else - { - SuccessOrExit(error = mReceivedMessage->AppendBytes(aBuf, static_cast(missingBytes))); - aLength -= missingBytes; - aBuf += missingBytes; - } + if (missingBytes > aLength) + { + error = mReceivedMessage->AppendBytes(aBuf, aLength); + ExitNow(); } - IgnoreError(mReceivedMessage->Read(0, tlv)); + SuccessOrExit(error = mReceivedMessage->AppendBytes(aBuf, static_cast(missingBytes))); + aLength -= missingBytes; + aBuf += missingBytes; + } - if (tlv.IsExtended()) - { - ot::ExtendedTlv extTlv; - requiredBytes = sizeof(extTlv); + IgnoreError(mReceivedMessage->Read(0, tlv)); - if (mReceivedMessage->GetLength() < requiredBytes) - { - continue; - } + if (tlv.IsExtended()) + { + ExtendedTlv extTlv; - IgnoreError(mReceivedMessage->Read(0, extTlv)); - requiredBytes = extTlv.GetSize(); - offset = sizeof(extTlv); - } - else - { - requiredBytes = tlv.GetSize(); - offset = sizeof(tlv); - } + requiredBytes = sizeof(extTlv); if (mReceivedMessage->GetLength() < requiredBytes) { continue; } - // TLV fully loaded - let TCAT agent handle it, if connected - if (Get().IsConnected()) + IgnoreError(mReceivedMessage->Read(0, extTlv)); + requiredBytes = extTlv.GetSize(); + offset = sizeof(extTlv); + } + else + { + requiredBytes = tlv.GetSize(); + offset = sizeof(tlv); + } + + if (mReceivedMessage->GetLength() < requiredBytes) + { + continue; + } + + // TLV fully loaded - let TCAT agent handle it, if connected + + if (Get().IsConnected()) + { + Error errorTcatAgent = kErrorNone; + + IgnoreError(Flush()); + + if (mSendMessage == nullptr) { - Error errorTcatAgent = kErrorNone; - - IgnoreError(Flush()); - - if (mSendMessage == nullptr) - { - mSendMessage = Get().Allocate(Message::kTypeBle); - VerifyOrExit(mSendMessage != nullptr, error = kErrorNoBufs); - } - - errorTcatAgent = Get().HandleSingleTlv(*mReceivedMessage, *mSendMessage); - - if (errorTcatAgent != kErrorNone) - { - // kErrorAbort indicates that a Disconnect command TLV has been received. - if (errorTcatAgent == kErrorAbort) - { - LogInfo("Disconnecting TCAT client."); - } - else - { - // fatal error: TLV integrity and order can't be guaranteed anymore for this connection. - LogWarnOnError(errorTcatAgent, "HandleSingleTlv"); - } - Disconnect(); - // BleSecure is not stopped here, it must remain active in advertising state and - // must be ready to receive a next TCAT commissioner. - ExitNow(); - } - SuccessOrExit(error = Flush()); // send out the response generated by the TcatAgent - } - else - { - // if the TCAT agent is not connected - do callback using the TLV's value as the message - mReceivedMessage->SetOffset(static_cast(offset)); - mReceiveCallback.InvokeIfSet(&GetInstance(), mReceivedMessage, static_cast(offset), - OT_TCAT_APPLICATION_PROTOCOL_NONE); + mSendMessage = Get().Allocate(Message::kTypeBle); + VerifyOrExit(mSendMessage != nullptr, error = kErrorNoBufs); } - IgnoreError(mReceivedMessage->SetLength(0)); // also sets the offset to 0 - requiredBytes = sizeof(Tlv); // set for the next TLV - } // while (aLength > 0) - } + errorTcatAgent = Get().HandleSingleTlv(*mReceivedMessage, *mSendMessage); + + switch (errorTcatAgent) + { + case kErrorNone: + SuccessOrExit(error = Flush()); + break; + + case kErrorAbort: + // `kErrorAbort` indicates that a Disconnect command TLV + // has been received. + LogInfo("Disconnecting TCAT client."); + errorTcatAgent = kErrorNone; + + OT_FALL_THROUGH; + + default: + LogWarnOnError(errorTcatAgent, "HandleSingleTlv"); + + // BleSecure is disconnected but not stopped here, it + // must remain active in advertising state and must be + // ready to receive a next TCAT commissioner. + + Disconnect(); + ExitNow(); + } + } + else + { + // If the TCAT agent is not connected - do callback using + // the TLV's value as the message + mReceivedMessage->SetOffset(static_cast(offset)); + mReceiveCallback.InvokeIfSet(&GetInstance(), mReceivedMessage, static_cast(offset), + OT_TCAT_APPLICATION_PROTOCOL_NONE); + } + + IgnoreError(mReceivedMessage->SetLength(0)); + requiredBytes = sizeof(Tlv); + + } // while loop exit: if (error != kErrorNone) { - // in this very rare case, a partial TLV is received, or a TLV has been fully dropped, or Flush() failed. - // mSendMessage is most likely not initialized; so appending a GeneralError status TLV to mSendMessage would - // fail also. In this case it's not possible to recover TLV integrity and client/server sync. - // It's handled by logging the error and (necessarily) closing the secure connection. + // In this very rare case, a partial TLV is received, or a TLV + // has been fully dropped, or `Flush()` failed. `mSendMessage` is + // most likely not initialized; so appending a `GeneralError` + // status TLV to `mSendMessage` would fail also. In this case + // it's not possible to recover TLV integrity and client/server + // sync. It's handled by logging the error and (necessarily) + // closing the secure connection. + LogCritOnError(error, "HandleTlsReceive"); Disconnect(); }