mirror of
https://github.com/espressif/openthread.git
synced 2026-09-11 19:50:05 +00:00
[discover-scan] simplify and enhance discovery response parsing (#12293)
This commit enhances the parsing of discovery response messages in `DiscoverScanner::HandleDiscoveryResponse()`. The parsing logic is updated to first restrict the message to the content of the `Discovery` TLV. This allows for a simpler and more robust processing of the nested MeshCoP sub-TLVs. Instead of looping through all sub-TLVs, the new approach directly looks for each expected sub-TLV. This change provides a clearer distinction between required TLVs (`DiscoveryResponseTlv`, `ExtendedPanIdTlv`, `NetworkNameTlv`) and optional ones. The handling of optional TLVs like `JoinerUdpPortTlv` and `SteeringDataTlv` is improved to explicitly manage the case where they are not found. Additionally, this commit includes minor cleanups to `SteeringDataTlv` to simplify its implementation.
This commit is contained in:
@@ -349,15 +349,12 @@ public:
|
||||
*
|
||||
* @returns The Steering Data length.
|
||||
*/
|
||||
uint8_t GetSteeringDataLength(void) const
|
||||
{
|
||||
return GetLength() <= sizeof(mSteeringData) ? GetLength() : sizeof(mSteeringData);
|
||||
}
|
||||
uint8_t GetSteeringDataLength(void) const { return Min<uint8_t>(GetLength(), SteeringData::kMaxLength); }
|
||||
|
||||
/**
|
||||
* Sets all bits in the Bloom Filter to zero.
|
||||
*/
|
||||
void Clear(void) { memset(mSteeringData, 0, GetSteeringDataLength()); }
|
||||
void Clear(void) { ClearAllBytes(mSteeringData); }
|
||||
|
||||
/**
|
||||
* Copies the Steering Data from the TLV into a given `SteeringData` variable.
|
||||
|
||||
@@ -317,19 +317,24 @@ exit:
|
||||
|
||||
void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
ScanResult result;
|
||||
OffsetRange offsetRange;
|
||||
Tlv::ParsedInfo tlvInfo;
|
||||
bool didCheckSteeringData = false;
|
||||
Error error = kErrorNone;
|
||||
ScanResult result;
|
||||
OffsetRange offsetRange;
|
||||
MeshCoP::DiscoveryResponseTlvValue respTlvValue;
|
||||
MeshCoP::SteeringDataTlv steeringDataTlv;
|
||||
|
||||
Mle::Log(Mle::kMessageReceive, Mle::kTypeDiscoveryResponse, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
|
||||
VerifyOrExit(mState == kStateScanning, error = kErrorDrop);
|
||||
|
||||
// Find MLE Discovery TLV
|
||||
// Find MLE Discovery TLV and restrict the message to this TLV value,
|
||||
// so we can parse all the included MeshCoP sub-TLVs within this TLV.
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRxInfo.mMessage, Tlv::kDiscovery, offsetRange));
|
||||
|
||||
aRxInfo.mMessage.SetOffset(offsetRange.GetOffset());
|
||||
IgnoreError(aRxInfo.mMessage.SetLength(offsetRange.GetEndOffset()));
|
||||
|
||||
ClearAllBytes(result);
|
||||
result.mDiscover = true;
|
||||
result.mPanId = aRxInfo.mMessage.GetPanId();
|
||||
@@ -339,68 +344,52 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
|
||||
|
||||
AsCoreType(&result.mExtAddress).SetFromIid(aRxInfo.mMessageInfo.GetPeerAddr().GetIid());
|
||||
|
||||
for (; !offsetRange.IsEmpty(); offsetRange.AdvanceOffset(tlvInfo.GetSize()))
|
||||
// Required TLVs
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<MeshCoP::DiscoveryResponseTlv>(aRxInfo.mMessage, respTlvValue));
|
||||
result.mVersion = respTlvValue.GetVersion();
|
||||
result.mIsNative = respTlvValue.GetNativeCommissionerFlag();
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, AsCoreType(&result.mExtendedPanId)));
|
||||
SuccessOrExit(error = Tlv::Find<MeshCoP::NetworkNameTlv>(aRxInfo.mMessage, result.mNetworkName.m8));
|
||||
|
||||
// Optional TLVs
|
||||
|
||||
switch (Tlv::Find<MeshCoP::JoinerUdpPortTlv>(aRxInfo.mMessage, result.mJoinerUdpPort))
|
||||
{
|
||||
SuccessOrExit(error = tlvInfo.ParseFrom(aRxInfo.mMessage, offsetRange));
|
||||
|
||||
if (tlvInfo.mIsExtended)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (tlvInfo.mType)
|
||||
{
|
||||
case MeshCoP::Tlv::kDiscoveryResponse:
|
||||
{
|
||||
MeshCoP::DiscoveryResponseTlvValue respTlvValue;
|
||||
|
||||
SuccessOrExit(error = Tlv::Read<MeshCoP::DiscoveryResponseTlv>(aRxInfo.mMessage, offsetRange.GetOffset(),
|
||||
respTlvValue));
|
||||
result.mVersion = respTlvValue.GetVersion();
|
||||
result.mIsNative = respTlvValue.GetNativeCommissionerFlag();
|
||||
break;
|
||||
}
|
||||
|
||||
case MeshCoP::Tlv::kExtendedPanId:
|
||||
SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offsetRange.GetOffset(),
|
||||
AsCoreType(&result.mExtendedPanId)));
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kNetworkName:
|
||||
SuccessOrExit(error = Tlv::Read<MeshCoP::NetworkNameTlv>(aRxInfo.mMessage, offsetRange.GetOffset(),
|
||||
result.mNetworkName.m8));
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kSteeringData:
|
||||
if (!tlvInfo.mValueOffsetRange.IsEmpty())
|
||||
{
|
||||
MeshCoP::SteeringData &steeringData = AsCoreType(&result.mSteeringData);
|
||||
OffsetRange valueOffsetRange = tlvInfo.mValueOffsetRange;
|
||||
|
||||
valueOffsetRange.ShrinkLength(MeshCoP::SteeringData::kMaxLength);
|
||||
IgnoreError(steeringData.Init(static_cast<uint8_t>(valueOffsetRange.GetLength())));
|
||||
aRxInfo.mMessage.ReadBytes(valueOffsetRange, steeringData.GetData());
|
||||
|
||||
if (mEnableFiltering)
|
||||
{
|
||||
VerifyOrExit(steeringData.Contains(mFilterIndexes));
|
||||
}
|
||||
|
||||
didCheckSteeringData = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kJoinerUdpPort:
|
||||
SuccessOrExit(error = Tlv::Read<MeshCoP::JoinerUdpPortTlv>(aRxInfo.mMessage, offsetRange.GetOffset(),
|
||||
result.mJoinerUdpPort));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case kErrorNone:
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
result.mJoinerUdpPort = 0;
|
||||
break;
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
VerifyOrExit(!mEnableFiltering || didCheckSteeringData);
|
||||
switch (Tlv::FindTlv(aRxInfo.mMessage, steeringDataTlv))
|
||||
{
|
||||
case kErrorNone:
|
||||
if (steeringDataTlv.IsValid())
|
||||
{
|
||||
MeshCoP::SteeringData &steeringData = AsCoreType(&result.mSteeringData);
|
||||
|
||||
IgnoreError(steeringDataTlv.CopyTo(steeringData));
|
||||
|
||||
if (mEnableFiltering)
|
||||
{
|
||||
VerifyOrExit(steeringData.Contains(mFilterIndexes));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kErrorNotFound:
|
||||
VerifyOrExit(!mEnableFiltering);
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
mCallback.InvokeIfSet(&result);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user