[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.
This commit is contained in:
Abtin Keshavarzian
2026-05-18 19:11:41 -07:00
committed by GitHub
parent b42e3747ee
commit 9d5539844c
+98 -86
View File
@@ -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<uint16_t>(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<uint16_t>(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<MeshCoP::TcatAgent>().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<MeshCoP::TcatAgent>().IsConnected())
{
Error errorTcatAgent = kErrorNone;
IgnoreError(Flush());
if (mSendMessage == nullptr)
{
Error errorTcatAgent = kErrorNone;
IgnoreError(Flush());
if (mSendMessage == nullptr)
{
mSendMessage = Get<MessagePool>().Allocate(Message::kTypeBle);
VerifyOrExit(mSendMessage != nullptr, error = kErrorNoBufs);
}
errorTcatAgent = Get<MeshCoP::TcatAgent>().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<uint16_t>(offset));
mReceiveCallback.InvokeIfSet(&GetInstance(), mReceivedMessage, static_cast<int32_t>(offset),
OT_TCAT_APPLICATION_PROTOCOL_NONE);
mSendMessage = Get<MessagePool>().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<MeshCoP::TcatAgent>().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<uint16_t>(offset));
mReceiveCallback.InvokeIfSet(&GetInstance(), mReceivedMessage, static_cast<int32_t>(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();
}