mirror of
https://github.com/espressif/openthread.git
synced 2026-07-27 22:37:45 +00:00
[mac] introduce ScanResult to encapsulate scan results (#12453)
This commit introduces the `ScanResult` class, which inherits from `otActiveScanResult`. This new class provides C++ idiomatic getter methods that return core OpenThread types (e.g., `ExtAddress`, `ExtendedPanId`, `NetworkName`) instead of raw C structures. The logic for parsing a received Beacon frame and populating the result fields is moved into `ScanResult::PopulateFromBeacon()`. This centralizes the parsing logic and allows it to be reused across different modules. Consequently, `Mac`, `DiscoverScanner`, `Seeker`, and `PanIdQueryServer` are updated to utilize `ScanResult`. The `Mac` class is also updated to use the `Callback` template for the active scan handler, replacing the previous raw function pointer and context.
This commit is contained in:
@@ -541,6 +541,8 @@ openthread_core_files = [
|
||||
"mac/mac_links.hpp",
|
||||
"mac/mac_types.cpp",
|
||||
"mac/mac_types.hpp",
|
||||
"mac/scan_result.cpp",
|
||||
"mac/scan_result.hpp",
|
||||
"mac/sub_mac.cpp",
|
||||
"mac/sub_mac.hpp",
|
||||
"mac/sub_mac_callbacks.cpp",
|
||||
|
||||
@@ -158,6 +158,7 @@ set(COMMON_SOURCES
|
||||
mac/mac_header_ie.cpp
|
||||
mac/mac_links.cpp
|
||||
mac/mac_types.cpp
|
||||
mac/scan_result.cpp
|
||||
mac/sub_mac.cpp
|
||||
mac/sub_mac_callbacks.cpp
|
||||
mac/sub_mac_csl_receiver.cpp
|
||||
|
||||
+14
-69
@@ -93,8 +93,7 @@ Mac::Mac(Instance &aInstance)
|
||||
, mWakeupListenInterval(kDefaultWedListenInterval)
|
||||
, mWakeupListenDuration(kDefaultWedListenDuration)
|
||||
#endif
|
||||
, mActiveScanHandler(nullptr) // Initialize `mActiveScanHandler` and `mEnergyScanHandler` union
|
||||
, mScanHandlerContext(nullptr)
|
||||
, mActiveScanCallback()
|
||||
, mLinks(aInstance)
|
||||
, mOperationTask(aInstance)
|
||||
, mTimer(aInstance)
|
||||
@@ -141,15 +140,14 @@ void Mac::SetEnabled(bool aEnable)
|
||||
}
|
||||
}
|
||||
|
||||
Error Mac::ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext)
|
||||
Error Mac::ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ScanResult::Handler aHandler, void *aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
|
||||
VerifyOrExit(!IsActiveScanInProgress() && !IsEnergyScanInProgress(), error = kErrorBusy);
|
||||
|
||||
mActiveScanHandler = aHandler;
|
||||
mScanHandlerContext = aContext;
|
||||
mActiveScanCallback.Set(aHandler, aContext);
|
||||
|
||||
if (aScanDuration == 0)
|
||||
{
|
||||
@@ -169,8 +167,7 @@ Error Mac::EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScan
|
||||
VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
|
||||
VerifyOrExit(!IsActiveScanInProgress() && !IsEnergyScanInProgress(), error = kErrorBusy);
|
||||
|
||||
mEnergyScanHandler = aHandler;
|
||||
mScanHandlerContext = aContext;
|
||||
mEnergyScanCallback.Set(aHandler, aContext);
|
||||
|
||||
Scan(kOperationEnergyScan, aScanChannels, aScanDuration);
|
||||
|
||||
@@ -225,57 +222,6 @@ bool Mac::IsInTransmitState(void) const
|
||||
return retval;
|
||||
}
|
||||
|
||||
Error Mac::ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Address address;
|
||||
#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
|
||||
const BeaconPayload *beaconPayload = nullptr;
|
||||
const Beacon *beacon = nullptr;
|
||||
uint16_t payloadLength;
|
||||
#endif
|
||||
|
||||
ClearAllBytes(aResult);
|
||||
|
||||
VerifyOrExit(aBeaconFrame != nullptr, error = kErrorInvalidArgs);
|
||||
|
||||
VerifyOrExit(aBeaconFrame->GetType() == Frame::kTypeBeacon, error = kErrorParse);
|
||||
SuccessOrExit(error = aBeaconFrame->GetSrcAddr(address));
|
||||
VerifyOrExit(address.IsExtended(), error = kErrorParse);
|
||||
aResult.mExtAddress = address.GetExtended();
|
||||
|
||||
if (kErrorNone != aBeaconFrame->GetSrcPanId(aResult.mPanId))
|
||||
{
|
||||
IgnoreError(aBeaconFrame->GetDstPanId(aResult.mPanId));
|
||||
}
|
||||
|
||||
aResult.mChannel = aBeaconFrame->GetChannel();
|
||||
aResult.mRssi = aBeaconFrame->GetRssi();
|
||||
aResult.mLqi = aBeaconFrame->GetLqi();
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
|
||||
payloadLength = aBeaconFrame->GetPayloadLength();
|
||||
|
||||
beacon = reinterpret_cast<const Beacon *>(aBeaconFrame->GetPayload());
|
||||
beaconPayload = reinterpret_cast<const BeaconPayload *>(beacon->GetPayload());
|
||||
|
||||
if ((payloadLength >= (sizeof(*beacon) + sizeof(*beaconPayload))) && beacon->IsValid() && beaconPayload->IsValid())
|
||||
{
|
||||
aResult.mVersion = beaconPayload->GetProtocolVersion();
|
||||
aResult.mIsJoinable = beaconPayload->IsJoiningPermitted();
|
||||
aResult.mIsNative = beaconPayload->IsNative();
|
||||
IgnoreError(AsCoreType(&aResult.mNetworkName).Set(beaconPayload->GetNetworkName()));
|
||||
VerifyOrExit(IsValidUtf8String(aResult.mNetworkName.m8), error = kErrorParse);
|
||||
aResult.mExtendedPanId = beaconPayload->GetExtendedPanId();
|
||||
}
|
||||
#endif
|
||||
|
||||
LogBeacon("Received");
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Mac::UpdateScanChannel(void)
|
||||
{
|
||||
Error error;
|
||||
@@ -308,18 +254,20 @@ void Mac::PerformActiveScan(void)
|
||||
|
||||
void Mac::ReportActiveScanResult(const RxFrame *aBeaconFrame)
|
||||
{
|
||||
VerifyOrExit(mActiveScanHandler != nullptr);
|
||||
VerifyOrExit(mActiveScanCallback.IsSet());
|
||||
|
||||
if (aBeaconFrame == nullptr)
|
||||
{
|
||||
mActiveScanHandler(nullptr, mScanHandlerContext);
|
||||
mActiveScanCallback.Invoke(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ActiveScanResult result;
|
||||
ScanResult result;
|
||||
|
||||
SuccessOrExit(ConvertBeaconToActiveScanResult(aBeaconFrame, result));
|
||||
mActiveScanHandler(&result, mScanHandlerContext);
|
||||
SuccessOrExit(result.PopulateFromBeacon(aBeaconFrame));
|
||||
LogBeacon("Received");
|
||||
|
||||
mActiveScanCallback.Invoke(&result);
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -356,10 +304,7 @@ exit:
|
||||
{
|
||||
FinishOperation();
|
||||
|
||||
if (mEnergyScanHandler != nullptr)
|
||||
{
|
||||
mEnergyScanHandler(nullptr, mScanHandlerContext);
|
||||
}
|
||||
mEnergyScanCallback.InvokeIfSet(nullptr);
|
||||
|
||||
PerformNextOperation();
|
||||
}
|
||||
@@ -369,12 +314,12 @@ void Mac::ReportEnergyScanResult(int8_t aRssi)
|
||||
{
|
||||
EnergyScanResult result;
|
||||
|
||||
VerifyOrExit((mEnergyScanHandler != nullptr) && (aRssi != Radio::kInvalidRssi));
|
||||
VerifyOrExit(mEnergyScanCallback.IsSet() && (aRssi != Radio::kInvalidRssi));
|
||||
|
||||
result.mChannel = mScanChannel;
|
||||
result.mMaxRssi = aRssi;
|
||||
|
||||
mEnergyScanHandler(&result, mScanHandlerContext);
|
||||
mEnergyScanCallback.Invoke(&result);
|
||||
|
||||
exit:
|
||||
return;
|
||||
|
||||
+4
-16
@@ -51,6 +51,7 @@
|
||||
#include "mac/mac_frame.hpp"
|
||||
#include "mac/mac_links.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "mac/scan_result.hpp"
|
||||
#include "mac/sub_mac.hpp"
|
||||
#include "radio/trel_link.hpp"
|
||||
#include "thread/key_manager.hpp"
|
||||
@@ -98,16 +99,6 @@ constexpr uint16_t kMinCslIePeriod = OPENTHREAD_CONFIG_MAC_CSL_MIN_PERIOD;
|
||||
constexpr uint32_t kDefaultWedListenInterval = OPENTHREAD_CONFIG_WED_LISTEN_INTERVAL;
|
||||
constexpr uint32_t kDefaultWedListenDuration = OPENTHREAD_CONFIG_WED_LISTEN_DURATION;
|
||||
|
||||
/**
|
||||
* Defines the function pointer called on receiving an IEEE 802.15.4 Beacon during an Active Scan.
|
||||
*/
|
||||
typedef otHandleActiveScanResult ActiveScanHandler;
|
||||
|
||||
/**
|
||||
* Defines an Active Scan result.
|
||||
*/
|
||||
typedef otActiveScanResult ActiveScanResult;
|
||||
|
||||
/**
|
||||
* Defines the function pointer which is called during an Energy Scan when the scan result for a channel is
|
||||
* ready or when the scan completes.
|
||||
@@ -151,7 +142,7 @@ public:
|
||||
* @retval kErrorNone Successfully scheduled the Active Scan request.
|
||||
* @retval kErrorBusy Could not schedule the scan (a scan is ongoing or scheduled).
|
||||
*/
|
||||
Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext);
|
||||
Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ScanResult::Handler aHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* Starts an IEEE 802.15.4 Energy Scan.
|
||||
@@ -847,7 +838,6 @@ private:
|
||||
Error UpdateScanChannel(void);
|
||||
void PerformActiveScan(void);
|
||||
void ReportActiveScanResult(const RxFrame *aBeaconFrame);
|
||||
Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult);
|
||||
void PerformEnergyScan(void);
|
||||
void ReportEnergyScanResult(int8_t aRssi);
|
||||
|
||||
@@ -926,12 +916,10 @@ private:
|
||||
#endif
|
||||
union
|
||||
{
|
||||
ActiveScanHandler mActiveScanHandler;
|
||||
EnergyScanHandler mEnergyScanHandler;
|
||||
ScanResult::ScanCallback mActiveScanCallback;
|
||||
Callback<EnergyScanHandler> mEnergyScanCallback;
|
||||
};
|
||||
|
||||
void *mScanHandlerContext;
|
||||
|
||||
Links mLinks;
|
||||
OperationTask mOperationTask;
|
||||
MacTimer mTimer;
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2026, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes implementation of methods in `ScanResult`.
|
||||
*/
|
||||
|
||||
#include "scan_result.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
Error ScanResult::PopulateFromBeacon(const Mac::RxFrame *aBeaconFrame)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Mac::Address address;
|
||||
|
||||
Clear();
|
||||
|
||||
VerifyOrExit(aBeaconFrame != nullptr, error = kErrorInvalidArgs);
|
||||
|
||||
VerifyOrExit(aBeaconFrame->GetType() == Mac::Frame::kTypeBeacon, error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = aBeaconFrame->GetSrcAddr(address));
|
||||
VerifyOrExit(address.IsExtended(), error = kErrorParse);
|
||||
mExtAddress = address.GetExtended();
|
||||
|
||||
if (aBeaconFrame->GetSrcPanId(mPanId) != kErrorNone)
|
||||
{
|
||||
IgnoreError(aBeaconFrame->GetDstPanId(mPanId));
|
||||
}
|
||||
|
||||
mChannel = aBeaconFrame->GetChannel();
|
||||
mRssi = aBeaconFrame->GetRssi();
|
||||
mLqi = aBeaconFrame->GetLqi();
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
|
||||
{
|
||||
const Mac::Beacon *beacon;
|
||||
const Mac::BeaconPayload *beaconPayload;
|
||||
|
||||
VerifyOrExit(aBeaconFrame->GetPayloadLength() >= sizeof(Mac::Beacon) + sizeof(Mac::BeaconPayload));
|
||||
|
||||
beacon = reinterpret_cast<const Mac::Beacon *>(aBeaconFrame->GetPayload());
|
||||
VerifyOrExit(beacon->IsValid());
|
||||
|
||||
beaconPayload = reinterpret_cast<const Mac::BeaconPayload *>(beacon->GetPayload());
|
||||
VerifyOrExit(beaconPayload->IsValid());
|
||||
|
||||
mVersion = beaconPayload->GetProtocolVersion();
|
||||
mIsJoinable = beaconPayload->IsJoiningPermitted();
|
||||
mIsNative = beaconPayload->IsNative();
|
||||
mExtendedPanId = beaconPayload->GetExtendedPanId();
|
||||
|
||||
IgnoreError(AsCoreType(&mNetworkName).Set(beaconPayload->GetNetworkName()));
|
||||
VerifyOrExit(IsValidUtf8String(mNetworkName.m8), error = kErrorParse);
|
||||
}
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2026, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for scan result (discover scan or MAC active scan).
|
||||
*/
|
||||
|
||||
#ifndef OT_CORE_MAC_SCAN_RESULT_HPP_
|
||||
#define OT_CORE_MAC_SCAN_RESULT_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/link.h>
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/callback.hpp"
|
||||
#include "common/clearable.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "mac/mac_frame.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "meshcop/extended_panid.hpp"
|
||||
#include "meshcop/network_name.hpp"
|
||||
#include "meshcop/steering_data.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace Mac {
|
||||
class Mac;
|
||||
}
|
||||
|
||||
namespace Mle {
|
||||
class DiscoverScanner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a discover or active scan result.
|
||||
*/
|
||||
class ScanResult : public otActiveScanResult, public Clearable<ScanResult>
|
||||
{
|
||||
friend class ot::Mac::Mac;
|
||||
friend class ot::Mle::DiscoverScanner;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Represents the function pointer callback to notify scan result.
|
||||
*/
|
||||
typedef otHandleActiveScanResult Handler;
|
||||
|
||||
/**
|
||||
* Gets the IEEE 802.15.4 Extended Address.
|
||||
*
|
||||
* @returns A constant reference to the IEEE 802.15.4 Extended Address.
|
||||
*/
|
||||
const Mac::ExtAddress &GetExtAddress(void) const { return AsCoreType(&mExtAddress); }
|
||||
|
||||
/**
|
||||
* Gets the Thread Network Name.
|
||||
*
|
||||
* @returns A constant reference to the Thread Network Name.
|
||||
*/
|
||||
const MeshCoP::NetworkName &GetNetworkName(void) const { return AsCoreType(&mNetworkName); }
|
||||
|
||||
/**
|
||||
* Gets the Thread Extended PAN ID.
|
||||
*
|
||||
* @returns A constant reference to the Thread Extended PAN ID.
|
||||
*/
|
||||
const MeshCoP::ExtendedPanId &GetExtendedPanId(void) const { return AsCoreType(&mExtendedPanId); }
|
||||
|
||||
/**
|
||||
* Gets the Steering Data.
|
||||
*
|
||||
* @returns A constant reference to the Steering Data.
|
||||
*/
|
||||
const MeshCoP::SteeringData &GetSteeringData(void) const { return AsCoreType(&mSteeringData); }
|
||||
|
||||
/**
|
||||
* Gets the IEEE 802.15.4 PAN ID.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 PAN ID.
|
||||
*/
|
||||
Mac::PanId GetPanId(void) const { return mPanId; }
|
||||
|
||||
/**
|
||||
* Gets the Joiner UDP Port.
|
||||
*
|
||||
* @returns The Joiner UDP Port.
|
||||
*/
|
||||
uint16_t GetJoinerUdpPort(void) const { return mJoinerUdpPort; }
|
||||
|
||||
/**
|
||||
* Gets the IEEE 802.15.4 Channel.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 Channel.
|
||||
*/
|
||||
uint8_t GetChannel(void) const { return mChannel; }
|
||||
|
||||
/**
|
||||
* Gets the RSSI (dBm).
|
||||
*
|
||||
* @returns The RSSI.
|
||||
*/
|
||||
int8_t GetRssi(void) const { return mRssi; }
|
||||
|
||||
/**
|
||||
* Gets the LQI.
|
||||
*
|
||||
* @returns The LQI.
|
||||
*/
|
||||
uint8_t GetLqi(void) const { return mLqi; }
|
||||
|
||||
/**
|
||||
* Gets the Version.
|
||||
*
|
||||
* @returns The Version.
|
||||
*/
|
||||
uint8_t GetVersion(void) const { return mVersion; }
|
||||
|
||||
/**
|
||||
* Indicates whether the Native Commissioner flag is set.
|
||||
*
|
||||
* @retval TRUE If the Native Commissioner flag is set.
|
||||
* @retval FALSE If the Native Commissioner flag is not set.
|
||||
*/
|
||||
bool IsNative(void) const { return mIsNative; }
|
||||
|
||||
/**
|
||||
* Indicates whether the result is from MLE Discovery.
|
||||
*
|
||||
* @retval TRUE If the result is from MLE Discovery.
|
||||
* @retval FALSE If the result is not from MLE Discovery.
|
||||
*/
|
||||
bool IsDiscover(void) const { return mDiscover; }
|
||||
|
||||
/**
|
||||
* Indicates whether the Joining Permitted flag is set.
|
||||
*
|
||||
* @retval TRUE If the Joining Permitted flag is set.
|
||||
* @retval FALSE If the Joining Permitted flag is not set.
|
||||
*/
|
||||
bool IsJoinable(void) const { return mIsJoinable; }
|
||||
|
||||
private:
|
||||
typedef Callback<Handler> ScanCallback;
|
||||
|
||||
Error PopulateFromBeacon(const Mac::RxFrame *aBeaconFrame);
|
||||
};
|
||||
|
||||
/**
|
||||
* Declares a Scan handler method in a given class `Type`.
|
||||
*
|
||||
* This macro simplifies the definition of scan handler callback. It defines a `static` handler method which can be
|
||||
* used as a `Handler `callback function pointer. The `static` handler acts as a wrapper, casting the `aContext`
|
||||
* pointer back to a `Type` object and invoking its member method with the same `MethodName`.
|
||||
*
|
||||
* The `Type` class MUST implement the following member method which will be invoked by the `static` handler:
|
||||
*
|
||||
* void MethodName(const ScanResult *aScanResult);
|
||||
*
|
||||
* @param[in] Type The class `Type` in which scan result handler is declared.
|
||||
* @param[in] MethodName The handler method name.
|
||||
*/
|
||||
#define DeclareScanResultHandlerIn(Type, MethodName) \
|
||||
static void MethodName(otActiveScanResult *aScanResult, void *aContext) \
|
||||
{ \
|
||||
static_cast<Type *>(aContext)->MethodName(AsCoreTypePtr(aScanResult)); \
|
||||
} \
|
||||
\
|
||||
void MethodName(const ScanResult *aScanResult)
|
||||
|
||||
DefineCoreType(otActiveScanResult, ScanResult);
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OT_CORE_MAC_SCAN_RESULT_HPP_
|
||||
@@ -202,15 +202,14 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Seeker::Verdict Joiner::EvaluateScanResult(void *aContext, const Seeker::ScanResult *aResult)
|
||||
Seeker::Verdict Joiner::EvaluateScanResult(void *aContext, const otSeekerScanResult *aResult)
|
||||
{
|
||||
return static_cast<Joiner *>(aContext)->EvaluateScanResult(aResult);
|
||||
return static_cast<Joiner *>(aContext)->EvaluateScanResult(AsCoreTypePtr(aResult));
|
||||
}
|
||||
|
||||
Seeker::Verdict Joiner::EvaluateScanResult(const Seeker::ScanResult *aResult)
|
||||
Seeker::Verdict Joiner::EvaluateScanResult(const ScanResult *aResult)
|
||||
{
|
||||
Seeker::Verdict verdict = Seeker::kIgnore;
|
||||
const SteeringData *steeringData;
|
||||
Seeker::Verdict verdict = Seeker::kIgnore;
|
||||
|
||||
if (aResult == nullptr)
|
||||
{
|
||||
@@ -218,13 +217,11 @@ Seeker::Verdict Joiner::EvaluateScanResult(const Seeker::ScanResult *aResult)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
steeringData = AsCoreTypePtr(&aResult->mSteeringData);
|
||||
|
||||
// We prefer networks with an exact match of Joiner ID or
|
||||
// Discerner in the Steering Data compared to ones that allow all
|
||||
// Joiners.
|
||||
|
||||
if (steeringData->PermitsAllJoiners())
|
||||
if (aResult->GetSteeringData().PermitsAllJoiners())
|
||||
{
|
||||
verdict = Seeker::kAccept;
|
||||
ExitNow();
|
||||
@@ -232,11 +229,11 @@ Seeker::Verdict Joiner::EvaluateScanResult(const Seeker::ScanResult *aResult)
|
||||
|
||||
if (!mDiscerner.IsEmpty())
|
||||
{
|
||||
VerifyOrExit(steeringData->Contains(mDiscerner));
|
||||
VerifyOrExit(aResult->GetSteeringData().Contains(mDiscerner));
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(steeringData->Contains(mId));
|
||||
VerifyOrExit(aResult->GetSteeringData().Contains(mId));
|
||||
}
|
||||
|
||||
verdict = Seeker::kAcceptPreferred;
|
||||
|
||||
@@ -195,8 +195,8 @@ private:
|
||||
void FreeJoinerFinalizeMessage(void);
|
||||
void SendJoinerFinalize(void);
|
||||
void SendJoinerEntrustResponse(const Coap::Msg &aMsg);
|
||||
static Seeker::Verdict EvaluateScanResult(void *aContext, const Seeker::ScanResult *aResult);
|
||||
Seeker::Verdict EvaluateScanResult(const Seeker::ScanResult *aResult);
|
||||
static Seeker::Verdict EvaluateScanResult(void *aContext, const otSeekerScanResult *aResult);
|
||||
Seeker::Verdict EvaluateScanResult(const ScanResult *aResult);
|
||||
void HandleScanCompleted(void);
|
||||
static void HandleSecureCoapClientConnect(Dtls::Session::ConnectEvent aEvent, void *aContext);
|
||||
void HandleSecureCoapClientConnect(Dtls::Session::ConnectEvent aEvent);
|
||||
|
||||
+15
-21
@@ -110,12 +110,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Seeker::HandleDiscoverResult(ScanResult *aResult, void *aContext)
|
||||
{
|
||||
static_cast<Seeker *>(aContext)->HandleDiscoverResult(aResult);
|
||||
}
|
||||
|
||||
void Seeker::HandleDiscoverResult(ScanResult *aResult)
|
||||
void Seeker::HandleDiscoverResult(const ScanResult *aResult)
|
||||
{
|
||||
bool preferred = false;
|
||||
|
||||
@@ -128,8 +123,8 @@ void Seeker::HandleDiscoverResult(ScanResult *aResult)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
VerifyOrExit(aResult->mJoinerUdpPort > 0);
|
||||
VerifyOrExit(AsCoreType(&aResult->mSteeringData).IsValid());
|
||||
VerifyOrExit(aResult->GetJoinerUdpPort() > 0);
|
||||
VerifyOrExit(aResult->GetSteeringData().IsValid());
|
||||
|
||||
switch (mScanEvaluator.Invoke(aResult))
|
||||
{
|
||||
@@ -152,20 +147,19 @@ exit:
|
||||
|
||||
void Seeker::SaveCandidate(const ScanResult &aResult, bool aPreferred)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
const MeshCoP::ExtendedPanId &extPanId = AsCoreType(&aResult.mExtendedPanId);
|
||||
bool shouldPushAsNew = false;
|
||||
CandidateEntry entry;
|
||||
Error error = kErrorNone;
|
||||
bool shouldPushAsNew = false;
|
||||
CandidateEntry entry;
|
||||
|
||||
entry.MarkAsEmpty();
|
||||
|
||||
if (mCandidates.FindMatching(entry, extPanId, AsCoreType(&aResult.mExtAddress)) == kErrorNone)
|
||||
if (mCandidates.FindMatching(entry, aResult.GetExtendedPanId(), aResult.GetExtAddress()) == kErrorNone)
|
||||
{
|
||||
entry.Log(Candidate::kReplace);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t count = CountAndSelectLeastFavoredCandidateFor(extPanId, entry);
|
||||
uint16_t count = CountAndSelectLeastFavoredCandidateFor(aResult.GetExtendedPanId(), entry);
|
||||
|
||||
if ((count == kMaxCandidatesPerNetwork) || ((count > 0) && mCandidates.IsFull()))
|
||||
{
|
||||
@@ -412,12 +406,12 @@ exit:
|
||||
|
||||
void Seeker::Candidate::SetFrom(const ScanResult &aResult, bool aPreferred)
|
||||
{
|
||||
mExtPanId = AsCoreType(&aResult.mExtendedPanId);
|
||||
mExtAddr = AsCoreType(&aResult.mExtAddress);
|
||||
mPanId = aResult.mPanId;
|
||||
mJoinerUdpPort = aResult.mJoinerUdpPort;
|
||||
mChannel = aResult.mChannel;
|
||||
mRssi = aResult.mRssi;
|
||||
mExtPanId = aResult.GetExtendedPanId();
|
||||
mExtAddr = aResult.GetExtAddress();
|
||||
mPanId = aResult.GetPanId();
|
||||
mJoinerUdpPort = aResult.GetJoinerUdpPort();
|
||||
mChannel = aResult.GetChannel();
|
||||
mRssi = aResult.GetRssi();
|
||||
mPreferred = aPreferred;
|
||||
mConnAttempted = false;
|
||||
}
|
||||
@@ -429,7 +423,7 @@ bool Seeker::Candidate::IsFavoredOver(const Candidate &aOther) const
|
||||
|
||||
bool Seeker::Candidate::IsFavoredOver(const ScanResult &aResult, bool aPreferred) const
|
||||
{
|
||||
return IsFavoredOver(aResult.mRssi, aPreferred);
|
||||
return IsFavoredOver(aResult.GetRssi(), aPreferred);
|
||||
}
|
||||
|
||||
bool Seeker::Candidate::IsFavoredOver(int8_t aRssi, bool aPreferred) const
|
||||
|
||||
@@ -70,8 +70,6 @@ class Seeker : public InstanceLocator, private NonCopyable
|
||||
friend class ot::UnitTester;
|
||||
|
||||
public:
|
||||
typedef otSeekerScanResult ScanResult; ///< Discover Scan result.
|
||||
|
||||
typedef otSeekerVerdict Verdict; ///< A verdict returned from `ScanEvaluator` evaluating a Discover Scan result.
|
||||
|
||||
static constexpr Verdict kAccept = OT_SEEKER_ACCEPT; ///< Scan result is acceptable.
|
||||
@@ -229,17 +227,17 @@ private:
|
||||
void ReplaceWithIfFavored(const CandidateEntry &aEntry);
|
||||
};
|
||||
|
||||
State GetState(void) const { return mState; }
|
||||
void SetState(State aState) { mState = aState; }
|
||||
static void HandleDiscoverResult(ScanResult *aResult, void *aContext);
|
||||
void HandleDiscoverResult(ScanResult *aResult);
|
||||
void SaveCandidate(const ScanResult &aResult, bool aPreferred);
|
||||
Error EvictCandidate(CandidateEntry &aEntry);
|
||||
Error SelectNextCandidate(CandidateEntry &aEntry);
|
||||
uint16_t CountAndSelectLeastFavoredCandidateFor(const MeshCoP::ExtendedPanId &aExtPanId,
|
||||
CandidateEntry &aEntry) const;
|
||||
State GetState(void) const { return mState; }
|
||||
void SetState(State aState) { mState = aState; }
|
||||
void SaveCandidate(const ScanResult &aResult, bool aPreferred);
|
||||
Error EvictCandidate(CandidateEntry &aEntry);
|
||||
Error SelectNextCandidate(CandidateEntry &aEntry);
|
||||
uint16_t CountAndSelectLeastFavoredCandidateFor(const MeshCoP::ExtendedPanId &aExtPanId,
|
||||
CandidateEntry &aEntry) const;
|
||||
Error SelectMostFavoredCandidateFor(const MeshCoP::ExtendedPanId &aExtPanId, CandidateEntry &aFavoredEntry) const;
|
||||
|
||||
DeclareScanResultHandlerIn(Seeker, HandleDiscoverResult);
|
||||
|
||||
State mState;
|
||||
uint16_t mUdpPort;
|
||||
Callback<ScanEvaluator> mScanEvaluator;
|
||||
|
||||
@@ -58,7 +58,7 @@ Error DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
|
||||
bool aJoiner,
|
||||
bool aEnableFiltering,
|
||||
const FilterIndexes *aFilterIndexes,
|
||||
Handler aCallback,
|
||||
ScanResult::Handler aHandler,
|
||||
void *aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -88,7 +88,7 @@ Error DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
|
||||
}
|
||||
}
|
||||
|
||||
mCallback.Set(aCallback, aContext);
|
||||
mCallback.Set(aHandler, aContext);
|
||||
mShouldRestorePanId = false;
|
||||
mScanChannels = Get<Mac::Mac>().GetSupportedChannelMask();
|
||||
|
||||
@@ -332,7 +332,7 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
|
||||
aRxInfo.mMessage.SetOffset(offsetRange.GetOffset());
|
||||
IgnoreError(aRxInfo.mMessage.SetLength(offsetRange.GetEndOffset()));
|
||||
|
||||
ClearAllBytes(result);
|
||||
result.Clear();
|
||||
result.mDiscover = true;
|
||||
result.mPanId = aRxInfo.mMessage.GetPanId();
|
||||
result.mChannel = aRxInfo.mMessage.GetChannel();
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "mac/channel_mask.hpp"
|
||||
#include "mac/mac.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "mac/scan_result.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "thread/mle.hpp"
|
||||
|
||||
@@ -68,20 +69,6 @@ public:
|
||||
*/
|
||||
static constexpr uint32_t kDefaultScanDuration = Mac::kScanDurationDefault;
|
||||
|
||||
/**
|
||||
* Represents Discover Scan result.
|
||||
*/
|
||||
typedef otActiveScanResult ScanResult;
|
||||
|
||||
/**
|
||||
* Represents the handler function pointer called with any Discover Scan result or when the scan
|
||||
* completes.
|
||||
*
|
||||
* The handler function format is `void (*oHandler)(ScanResult *aResult, void *aContext);`. End of scan is
|
||||
* indicated by `aResult` pointer being set to `nullptr`.
|
||||
*/
|
||||
typedef otHandleActiveScanResult Handler;
|
||||
|
||||
/**
|
||||
* Represents the filter indexes, i.e., hash bit index values for the bloom filter (calculated from a
|
||||
* Joiner ID).
|
||||
@@ -109,7 +96,7 @@ public:
|
||||
* @param[in] aFilterIndexes A pointer to `FilterIndexes` to use for filtering (when enabled).
|
||||
* If set to `nullptr`, filter indexes are derived from hash of factory-assigned
|
||||
* EUI64.
|
||||
* @param[in] aCallback A pointer to a function that is called on receiving an MLE Discovery Response.
|
||||
* @param[in] aHandler A pointer to a function that is called on receiving an MLE Discovery Response.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
* @retval kErrorNone Successfully started a Thread Discovery Scan.
|
||||
@@ -122,7 +109,7 @@ public:
|
||||
bool aJoiner,
|
||||
bool aEnableFiltering,
|
||||
const FilterIndexes *aFilterIndexes,
|
||||
Handler aCallback,
|
||||
ScanResult::Handler aHandler,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
@@ -176,15 +163,15 @@ private:
|
||||
using ScanTimer = TimerMilliIn<DiscoverScanner, &DiscoverScanner::HandleTimer>;
|
||||
using ScanDoneTask = TaskletIn<DiscoverScanner, &DiscoverScanner::HandleScanDoneTask>;
|
||||
|
||||
Callback<Handler> mCallback;
|
||||
ScanDoneTask mScanDoneTask;
|
||||
ScanTimer mTimer;
|
||||
FilterIndexes mFilterIndexes;
|
||||
Mac::ChannelMask mScanChannels;
|
||||
State mState;
|
||||
uint8_t mScanChannel;
|
||||
bool mEnableFiltering : 1;
|
||||
bool mShouldRestorePanId : 1;
|
||||
ScanResult::ScanCallback mCallback;
|
||||
ScanDoneTask mScanDoneTask;
|
||||
ScanTimer mTimer;
|
||||
FilterIndexes mFilterIndexes;
|
||||
Mac::ChannelMask mScanChannels;
|
||||
State mState;
|
||||
uint8_t mScanChannel;
|
||||
bool mEnableFiltering : 1;
|
||||
bool mShouldRestorePanId : 1;
|
||||
#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE
|
||||
uint8_t mAdvDataLength;
|
||||
uint8_t mAdvData[kMaxAdvDataLength];
|
||||
|
||||
@@ -72,12 +72,7 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void PanIdQueryServer::HandleScanResult(Mac::ActiveScanResult *aScanResult, void *aContext)
|
||||
{
|
||||
static_cast<PanIdQueryServer *>(aContext)->HandleScanResult(aScanResult);
|
||||
}
|
||||
|
||||
void PanIdQueryServer::HandleScanResult(Mac::ActiveScanResult *aScanResult)
|
||||
void PanIdQueryServer::HandleScanResult(const ScanResult *aScanResult)
|
||||
{
|
||||
if (aScanResult != nullptr)
|
||||
{
|
||||
|
||||
@@ -64,13 +64,11 @@ private:
|
||||
|
||||
template <Uri kUri> void HandleTmf(Coap::Msg &aMsg);
|
||||
|
||||
static void HandleScanResult(Mac::ActiveScanResult *aScanResult, void *aContext);
|
||||
void HandleScanResult(Mac::ActiveScanResult *aScanResult);
|
||||
|
||||
void HandleTimer(void);
|
||||
DeclareScanResultHandlerIn(PanIdQueryServer, HandleScanResult);
|
||||
|
||||
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
void HandleTimer(void);
|
||||
void SendConflict(void);
|
||||
|
||||
using DelayTimer = TimerMilliIn<PanIdQueryServer, &PanIdQueryServer::HandleTimer>;
|
||||
|
||||
@@ -46,8 +46,8 @@ struct DiscoverContext
|
||||
mScanResults.Clear();
|
||||
}
|
||||
|
||||
bool mDiscoverDone;
|
||||
Array<Mle::DiscoverScanner::ScanResult, kMaxResults> mScanResults;
|
||||
bool mDiscoverDone;
|
||||
Array<ScanResult, kMaxResults> mScanResults;
|
||||
};
|
||||
|
||||
struct RequestCallbackContext : public Clearable<RequestCallbackContext>
|
||||
@@ -59,19 +59,20 @@ struct RequestCallbackContext : public Clearable<RequestCallbackContext>
|
||||
void HandleDiscoverResult(otActiveScanResult *aResult, void *aContext)
|
||||
{
|
||||
DiscoverContext *context = static_cast<DiscoverContext *>(aContext);
|
||||
ScanResult *result = AsCoreTypePtr(aResult);
|
||||
|
||||
VerifyOrQuit(aContext != nullptr);
|
||||
|
||||
Log(" HandleDiscoverResult() called%s", aResult == nullptr ? " (done)" : "");
|
||||
Log(" HandleDiscoverResult() called%s", result == nullptr ? " (done)" : "");
|
||||
|
||||
if (aResult == nullptr)
|
||||
if (result == nullptr)
|
||||
{
|
||||
context->mDiscoverDone = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrQuit(!context->mDiscoverDone);
|
||||
SuccessOrQuit(context->mScanResults.PushBack(*aResult));
|
||||
SuccessOrQuit(context->mScanResults.PushBack(*result));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,12 +96,12 @@ void HandleDiscoverRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aCon
|
||||
|
||||
void TestDiscoverScanRequestCallback(void)
|
||||
{
|
||||
Core nexus;
|
||||
Node &leader = nexus.CreateNode();
|
||||
Node &scanner = nexus.CreateNode();
|
||||
DiscoverContext resultContext;
|
||||
RequestCallbackContext requestContext;
|
||||
Mle::DiscoverScanner::ScanResult *result;
|
||||
Core nexus;
|
||||
Node &leader = nexus.CreateNode();
|
||||
Node &scanner = nexus.CreateNode();
|
||||
DiscoverContext resultContext;
|
||||
RequestCallbackContext requestContext;
|
||||
ScanResult *result;
|
||||
|
||||
Log("------------------------------------------------------------------------------------------------------");
|
||||
Log("TestDiscoverScanRequestCallback");
|
||||
@@ -148,11 +149,11 @@ void TestDiscoverScanRequestCallback(void)
|
||||
|
||||
result = &resultContext.mScanResults[0];
|
||||
|
||||
VerifyOrQuit(AsCoreType(&result->mExtAddress) == leader.Get<Mac::Mac>().GetExtAddress());
|
||||
VerifyOrQuit(AsCoreType(&result->mExtendedPanId) == leader.Get<MeshCoP::NetworkIdentity>().GetExtPanId());
|
||||
VerifyOrQuit(result->mPanId == leader.Get<Mac::Mac>().GetPanId());
|
||||
VerifyOrQuit(result->mChannel == leader.Get<Mac::Mac>().GetPanChannel());
|
||||
VerifyOrQuit(result->mDiscover);
|
||||
VerifyOrQuit(result->GetExtAddress() == leader.Get<Mac::Mac>().GetExtAddress());
|
||||
VerifyOrQuit(result->GetExtendedPanId() == leader.Get<MeshCoP::NetworkIdentity>().GetExtPanId());
|
||||
VerifyOrQuit(result->GetPanId() == leader.Get<Mac::Mac>().GetPanId());
|
||||
VerifyOrQuit(result->GetChannel() == leader.Get<Mac::Mac>().GetPanChannel());
|
||||
VerifyOrQuit(result->IsDiscover());
|
||||
}
|
||||
|
||||
} // namespace Nexus
|
||||
|
||||
@@ -39,7 +39,6 @@ class UnitTester
|
||||
{
|
||||
public:
|
||||
using Seeker = MeshCoP::Seeker;
|
||||
using ScanResult = MeshCoP::Seeker::ScanResult;
|
||||
using CandidateEntry = MeshCoP::Seeker::CandidateEntry;
|
||||
|
||||
static void CreateScanResult(ScanResult &aResult, uint64_t aExtPanId, uint64_t aExtAddr, int8_t aRssi)
|
||||
|
||||
Reference in New Issue
Block a user