diff --git a/doc/ot_api_doc.h b/doc/ot_api_doc.h index 8ca1b254e..07ebf90d1 100644 --- a/doc/ot_api_doc.h +++ b/doc/ot_api_doc.h @@ -128,6 +128,7 @@ * @brief Includes functions for the Operational Dataset API. * @defgroup api-thread-router Router/Leader * @brief This module includes functions for Thread Routers and Leaders. + * @defgroup api-seeker Seeker * @defgroup api-server Server * @defgroup api-steering-data Steering Data * diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake index cd6488564..49b63b498 100644 --- a/etc/cmake/options.cmake +++ b/etc/cmake/options.cmake @@ -252,6 +252,7 @@ ot_option(OT_PLATFORM_NETIF OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE "platform ne ot_option(OT_PLATFORM_POWER_CALIBRATION OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE "power calibration") ot_option(OT_PLATFORM_UDP OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE "platform UDP") ot_option(OT_REFERENCE_DEVICE OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE "test harness reference device") +ot_option(OT_SEEKER OPENTHREAD_CONFIG_SEEKER_ENABLE "seeker") ot_option(OT_SERVICE OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE "Network Data service") ot_option(OT_SETTINGS_RAM OPENTHREAD_SETTINGS_RAM "volatile-only storage of settings") ot_option(OT_SLAAC OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE "SLAAC address") diff --git a/include/openthread/BUILD.gn b/include/openthread/BUILD.gn index 94ffbd4d1..bba5c3573 100644 --- a/include/openthread/BUILD.gn +++ b/include/openthread/BUILD.gn @@ -120,6 +120,7 @@ source_set("openthread") { "radio_stats.h", "random_crypto.h", "random_noncrypto.h", + "seeker.h", "server.h", "sntp.h", "srp_client.h", diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 3f8af477e..287813296 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -52,7 +52,7 @@ extern "C" { * * @note This number versions both OpenThread platform and user APIs. */ -#define OPENTHREAD_API_VERSION (576) +#define OPENTHREAD_API_VERSION (577) /** * @addtogroup api-instance diff --git a/include/openthread/seeker.h b/include/openthread/seeker.h new file mode 100644 index 000000000..d125c7b8b --- /dev/null +++ b/include/openthread/seeker.h @@ -0,0 +1,192 @@ +/* + * 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 + * @brief + * This file implements the Thread Seeker role. + * + * The Seeker is a part of the Thread MeshCoP process. It is responsible for discovering nearby Joiner Router + * candidates, prioritizing them, and iterating through the list to select the best candidate for connection. + * It also operates as a sub-system of the `Joiner`, delegating control to the next layer to enable the + * implementation of alternative and custom joining protocols. + */ + +#ifndef OPENTHREAD_SEEKER_H_ +#define OPENTHREAD_SEEKER_H_ + +#include +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup api-seeker + * + * @brief + * This module includes functions for the Thread Seeker role. + * + * @note + * The functions in this module require `OPENTHREAD_CONFIG_SEEKER_ENABLE`. + * + * @{ + */ + +/** + * Represents a Discover Scan result. + */ +typedef otActiveScanResult otSeekerScanResult; + +/** + * Represents a verdict returned from the `otSeekerScanEvaluator` callback when evaluating a Discover Scan result. + */ +typedef enum otSeekerVerdict +{ + OT_SEEKER_ACCEPT, ///< The scan result is acceptable. + OT_SEEKER_ACCEPT_PREFERRED, ///< The scan result is acceptable and preferred. + OT_SEEKER_IGNORE, ///< The scan result should be ignored. +} otSeekerVerdict; + +/** + * Represents the callback function type used to evaluate a scan result or report the end of a scan. + * + * @param[in] aContext A pointer to the callback context. + * @param[in] aResult A pointer to the scan result to evaluate, or `NULL` to indicate scan completion. + * + * @returns The verdict for the scan result (Accept, AcceptPreferred, or Ignore). + * If @p aResult is `NULL` (scan complete), the return value is ignored. + */ +typedef otSeekerVerdict (*otSeekerScanEvaluator)(void *aContext, const otSeekerScanResult *aResult); + +/** + * Starts the Seeker operation. + * + * The Seeker generates and sets a random MAC address for anonymity, then initiates an MLE Discover Scan to find + * Joiner Router candidates. + * + * Found candidates are reported to the @p aScanEvaluator callback. Based on the returned `otSeekerVerdict`, the Seeker + * maintains a prioritized list of candidates for future connection attempts. + * + * @param[in] aInstance The OpenThread instance. + * @param[in] aScanEvaluator The callback function to evaluate scan results. + * @param[in] aContext An arbitrary context pointer to use with @p aScanEvaluator. + * + * @retval OT_ERROR_NONE Successfully started the Seeker. + * @retval OT_ERROR_BUSY The Seeker is already active (scanning or connecting). + * @retval OT_ERROR_INVALID_STATE The IPv6 interface is not enabled, or MLE is enabled. + */ +otError otSeekerStart(otInstance *aInstance, otSeekerScanEvaluator aScanEvaluator, void *aContext); + +/** + * Stops the Seeker operation. + * + * This function stops any ongoing discovery or connection process, unregisters the unsecure Joiner/Seeker UDP port, and + * clears internal state. If the Seeker is already stopped, this method has no effect. + * + * If the join process succeeds after a call to `otSeekerSetUpNextConnection()`, the caller MUST call this method to + * stop the Seeker and, importantly, unregister the Seeker UDP port as an unsecure port. + * + * @note If `otSeekerSetUpNextConnection()` returns `OT_ERROR_NOT_FOUND` (indicating the candidate list is exhausted), + * the Seeker stops automatically. + * + * @param[in] aInstance The OpenThread instance. + */ +void otSeekerStop(otInstance *aInstance); + +/** + * Indicates whether or not the Seeker is running. + * + * @param[in] aInstance The OpenThread instance. + * + * @retval TRUE The Seeker is active and running. + * @retval FALSE The Seeker is stopped. + */ +bool otSeekerIsRunning(otInstance *aInstance); + +/** + * Gets the Seeker UDP port (unsecure port). + * + * @param[in] aInstance The OpenThread instance. + * + * @returns The Seeker UDP port. + */ +uint16_t otSeekerGetUdpPort(otInstance *aInstance); + +/** + * Sets the Seeker UDP port (unsecure port). + * + * This UDP port can only be changed when the Seeker is not running. + * + * @param[in] aInstance The OpenThread instance. + * @param[in] aUdpPort The Seeker UDP port. + * + * @retval OT_ERROR_NONE Successfully set the Joiner/Seeker UDP port. + * @retval OT_ERROR_INVALID_STATE The Seeker is already running. + */ +otError otSeekerSetUdpPort(otInstance *aInstance, uint16_t aUdpPort); + +/** + * Selects the next best candidate and prepares the connection. + * + * This function MUST be called after the discovery scan has completed (indicated by the `otSeekerScanEvaluator` + * callback receiving `NULL`). Calling it before scan completion will result in `OT_ERROR_INVALID_STATE`. + * + * This function iterates through the discovered Joiner Router candidates in order of priority. For the selected + * candidate, it configures the radio channel and PAN ID, and populates @p aSockAddr with the candidate's address. + * It also registers the Seeker UDP port `otSeekerGetUdpPort()` as an unsecure port to allow a UDP connection to the + * candidate. The next layer code can start sending UDP messages to the given `otSockAddr` ensuring to use the unsecure + * Seeker UDP port as the source port. These messages are then forwarded by the Joiner Router onward to a + * Commissioner/Enroller connected via a Border Agent/Admitter. + * + * If the list is exhausted, this function returns `OT_ERROR_NOT_FOUND` and automatically calls `otSeekerStop()`, + * which removes the unsecure port and clears internal state. + * + * @param[out] aSockAddr A pointer to a socket address to output the candidate's address. + * + * @retval OT_ERROR_NONE Successfully set up the connection to the next candidate. + * @retval OT_ERROR_NOT_FOUND No more candidates are available (list exhausted). + * @retval OT_ERROR_INVALID_STATE The Seeker is not in a valid state (e.g. scan not yet completed). + */ +otError otSeekerSetUpNextConnection(otInstance *aInstance, otSockAddr *aSockAddr); + +/** + * @} + */ + +#ifdef __cplusplus +} // end of extern "C" +#endif + +#endif // OPENTHREAD_SEEKER_H_ diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 36cd2c487..ca3039ce9 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -370,6 +370,7 @@ openthread_core_files = [ "api/radio_stats_api.cpp", "api/random_crypto_api.cpp", "api/random_noncrypto_api.cpp", + "api/seeker_api.cpp", "api/server_api.cpp", "api/sntp_api.cpp", "api/srp_client_api.cpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c53798fc8..6f49a728d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -80,6 +80,7 @@ set(COMMON_SOURCES api/radio_stats_api.cpp api/random_crypto_api.cpp api/random_noncrypto_api.cpp + api/seeker_api.cpp api/server_api.cpp api/sntp_api.cpp api/srp_client_api.cpp diff --git a/src/core/api/seeker_api.cpp b/src/core/api/seeker_api.cpp new file mode 100644 index 000000000..24d76bedd --- /dev/null +++ b/src/core/api/seeker_api.cpp @@ -0,0 +1,63 @@ +/* + * 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 implements the OpenThread Seeker API. + */ + +#include "openthread-core-config.h" + +#if OPENTHREAD_CONFIG_SEEKER_ENABLE + +#include "instance/instance.hpp" + +using namespace ot; + +otError otSeekerStart(otInstance *aInstance, otSeekerScanEvaluator aScanEvaluator, void *aContext) +{ + return AsCoreType(aInstance).Get().Start(aScanEvaluator, aContext); +} + +void otSeekerStop(otInstance *aInstance) { AsCoreType(aInstance).Get().Stop(); } + +bool otSeekerIsRunning(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsRunning(); } + +uint16_t otSeekerGetUdpPort(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetUdpPort(); } + +otError otSeekerSetUdpPort(otInstance *aInstance, uint16_t aUdpPort) +{ + return AsCoreType(aInstance).Get().SetUdpPort(aUdpPort); +} + +otError otSeekerSetUpNextConnection(otInstance *aInstance, otSockAddr *aSockAddr) +{ + return AsCoreType(aInstance).Get().SetUpNextConnection(AsCoreType(aSockAddr)); +} + +#endif // OPENTHREAD_CONFIG_SEEKER_ENABLE diff --git a/src/core/config/joiner.h b/src/core/config/joiner.h index 3ce4d4f08..55d19f119 100644 --- a/src/core/config/joiner.h +++ b/src/core/config/joiner.h @@ -73,6 +73,20 @@ #define OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_SEEKER_ENABLE + * + * Define as 1 to enable Seeker functionality and `otSeeker` APIs. + * + * The Seeker is a part of the Thread MeshCoP process. It is responsible for discovering nearby Joiner Router + * candidates, prioritizing them, and iterating through the list to select the best candidate for connection. + * It also operates as a sub-system of the `Joiner`, delegating control to the next layer to enable the + * implementation of alternative and custom joining protocols. + */ +#ifndef OPENTHREAD_CONFIG_SEEKER_ENABLE +#define OPENTHREAD_CONFIG_SEEKER_ENABLE OPENTHREAD_CONFIG_JOINER_ENABLE +#endif + /** * @} */ diff --git a/src/core/instance/instance.cpp b/src/core/instance/instance.cpp index bd5678864..3f4ce2668 100644 --- a/src/core/instance/instance.cpp +++ b/src/core/instance/instance.cpp @@ -187,8 +187,10 @@ Instance::Instance(void) #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE , mTmfSecureAgent(*this) #endif -#if OPENTHREAD_CONFIG_JOINER_ENABLE +#if OPENTHREAD_CONFIG_SEEKER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE , mSeeker(*this) +#endif +#if OPENTHREAD_CONFIG_JOINER_ENABLE , mJoiner(*this) #endif #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE diff --git a/src/core/instance/instance.hpp b/src/core/instance/instance.hpp index ffc96e94e..285bda172 100644 --- a/src/core/instance/instance.hpp +++ b/src/core/instance/instance.hpp @@ -618,8 +618,10 @@ private: Tmf::SecureAgent mTmfSecureAgent; #endif -#if OPENTHREAD_CONFIG_JOINER_ENABLE +#if OPENTHREAD_CONFIG_SEEKER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE MeshCoP::Seeker mSeeker; +#endif +#if OPENTHREAD_CONFIG_JOINER_ENABLE MeshCoP::Joiner mJoiner; #endif @@ -959,9 +961,11 @@ template <> inline PanIdQueryClient &Instance::Get(void) { return mCommissioner. template <> inline Dnssd &Instance::Get(void) { return mDnssd; } #endif -#if OPENTHREAD_CONFIG_JOINER_ENABLE +#if OPENTHREAD_CONFIG_SEEKER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE template <> inline MeshCoP::Seeker &Instance::Get(void) { return mSeeker; } +#endif +#if OPENTHREAD_CONFIG_JOINER_ENABLE template <> inline MeshCoP::Joiner &Instance::Get(void) { return mJoiner; } #endif diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp index 9d48e546c..cfb067615 100644 --- a/src/core/meshcop/joiner.cpp +++ b/src/core/meshcop/joiner.cpp @@ -132,7 +132,7 @@ Error Joiner::Start(const char *aPskd, // (free allocated message, stop seeker, close agent, etc). shouldCleanup = true; - SuccessOrExit(error = Get().Bind(Seeker::kUdpPort)); + SuccessOrExit(error = Get().Bind(Get().GetUdpPort())); Get().SetConnectCallback(HandleSecureCoapClientConnect, this); Get().SetPsk(joinerPskd); diff --git a/src/core/meshcop/seeker.cpp b/src/core/meshcop/seeker.cpp index 333d1facc..d384f6f0f 100644 --- a/src/core/meshcop/seeker.cpp +++ b/src/core/meshcop/seeker.cpp @@ -33,7 +33,7 @@ #include "seeker.hpp" -#if OPENTHREAD_CONFIG_JOINER_ENABLE +#if OPENTHREAD_CONFIG_SEEKER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE #include "instance/instance.hpp" @@ -45,6 +45,7 @@ RegisterLogModule("Seeker"); Seeker::Seeker(Instance &aInstance) : InstanceLocator(aInstance) , mState(kStateStopped) + , mUdpPort(kDefaultUdpPort) , mCandidateIndex(0) { } @@ -87,13 +88,28 @@ void Seeker::Stop(void) case kStateDiscoverDone: break; case kStateConnecting: - IgnoreError(Get().RemoveUnsecurePort(kUdpPort)); + IgnoreError(Get().RemoveUnsecurePort(mUdpPort)); break; } SetState(kStateStopped); } +Error Seeker::SetUdpPort(uint16_t aUdpPort) +{ + Error error = kErrorNone; + + VerifyOrExit(!IsRunning(), error = kErrorInvalidState); + + VerifyOrExit(aUdpPort != mUdpPort); + LogInfo("UDP port changed: %u -> %u", mUdpPort, aUdpPort); + + mUdpPort = aUdpPort; + +exit: + return error; +} + void Seeker::HandleDiscoverResult(ScanResult *aResult, void *aContext) { static_cast(aContext)->HandleDiscoverResult(aResult); @@ -228,9 +244,9 @@ Error Seeker::SetUpNextConnection(Ip6::SockAddr &aSockAddr) Get().SetPanId(candidate->mPanId); SuccessOrExit(error = Get().SetPanChannel(candidate->mChannel)); - if (!Get().IsUnsecurePort(kUdpPort)) + if (!Get().IsUnsecurePort(mUdpPort)) { - SuccessOrExit(error = Get().AddUnsecurePort(kUdpPort)); + SuccessOrExit(error = Get().AddUnsecurePort(mUdpPort)); } SetState(kStateConnecting); @@ -246,4 +262,4 @@ exit: } // namespace MeshCoP } // namespace ot -#endif // OPENTHREAD_CONFIG_JOINER_ENABLE +#endif // OPENTHREAD_CONFIG_SEEKER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE diff --git a/src/core/meshcop/seeker.hpp b/src/core/meshcop/seeker.hpp index a0b5aabf4..5ef1b0bda 100644 --- a/src/core/meshcop/seeker.hpp +++ b/src/core/meshcop/seeker.hpp @@ -40,8 +40,11 @@ #include "openthread-core-config.h" -#if OPENTHREAD_CONFIG_JOINER_ENABLE +#if OPENTHREAD_CONFIG_SEEKER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE +#include + +#include "common/as_core_type.hpp" #include "common/callback.hpp" #include "common/error.hpp" #include "common/locator.hpp" @@ -59,30 +62,20 @@ namespace MeshCoP { class Seeker : public InstanceLocator, private NonCopyable { public: - static constexpr uint16_t kUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT; ///< The default Joiner UDP port. + typedef otSeekerScanResult ScanResult; ///< Discover Scan result. - typedef Mle::DiscoverScanner::ScanResult ScanResult; ///< Discover Scan result. + typedef otSeekerVerdict Verdict; ///< A verdict returned from `ScanEvaluator` evaluating a Discover Scan result. - /** - * Represents a verdict returned from `ScanEvaluator` when evaluating a Discover Scan result. - */ - enum Verdict : uint8_t - { - kAccept, ///< The scan result is acceptable. - kAcceptPreferred, ///< The scan result is acceptable and preferred. - kIgnore, ///< The scan result should be ignored. - }; + static constexpr Verdict kAccept = OT_SEEKER_ACCEPT; ///< Scan result is acceptable. + static constexpr Verdict kAcceptPreferred = OT_SEEKER_ACCEPT_PREFERRED; ///< Scan result is acceptable & preferred. + static constexpr Verdict kIgnore = OT_SEEKER_IGNORE; ///< Scan result should be ignored. /** * Represents the callback function type used to evaluate a scan result or report the end of a scan. * - * @param[in] aContext A pointer to the callback context. - * @param[in] aResult A pointer to the scan result to evaluate, or `nullptr` to indicate scan completion. - * - * @returns The verdict for the scan result (`kAccept`, `kAcceptPreferred`, or `kIgnore`). - * If @p aResult is `nullptr` (scan complete), the return value is ignored. + * See `otSeekerScanEvaluator` for more details. */ - typedef Verdict (*ScanEvaluator)(void *aContext, const ScanResult *aResult); + typedef otSeekerScanEvaluator ScanEvaluator; /** * Initializes the `Seeker` @@ -131,6 +124,25 @@ public: */ bool IsRunning(void) const { return GetState() != kStateStopped; } + /** + * Gets the Seeker UDP port. + * + * @returns The Seeker UDP port. + */ + uint16_t GetUdpPort(void) const { return mUdpPort; } + + /** + * Sets the Seeker UDP port. + * + * This method can only be called when the Seeker is not running. + * + * @param[in] aUdpPort The Seeker UDP port. + * + * @retval kErrorNone Successfully set the Seeker UDP port. + * @retval kErrorInvalidState The Seeker is already running. + */ + Error SetUdpPort(uint16_t aUdpPort); + /** * Selects the next best candidate and prepares the connection. * @@ -139,8 +151,8 @@ public: * * This method iterates through the discovered Joiner Router candidates in order of priority. For the selected * candidate, it configures the radio channel and PAN ID, and populates @p aSockAddr with the candidate's address. - * It also registers the Joiner UDP port `kUdpPort` as an unsecure port to allow UDP - * connection to the candidate. + * It also registers the Seeker UDP port (`GetUdpPort()`) as an unsecure port to allow UDP connection to the + * candidate. * * If the list is exhausted, this method returns `kErrorNotFound` and automatically calls `Stop()`, which removes * the unsecure port and clears internal state. @@ -154,7 +166,8 @@ public: Error SetUpNextConnection(Ip6::SockAddr &aSockAddr); private: - static constexpr uint16_t kMaxCandidates = OPENTHREAD_CONFIG_JOINER_MAX_CANDIDATES; + static constexpr uint16_t kDefaultUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT; + static constexpr uint16_t kMaxCandidates = OPENTHREAD_CONFIG_JOINER_MAX_CANDIDATES; enum State : uint8_t { @@ -183,6 +196,7 @@ private: static uint8_t CalculatePriority(int8_t aRssi, bool aPreferred); State mState; + uint16_t mUdpPort; Callback mScanEvaluator; Candidate mCandidates[kMaxCandidates]; uint16_t mCandidateIndex; @@ -191,6 +205,6 @@ private: } // namespace MeshCoP } // namespace ot -#endif // OPENTHREAD_CONFIG_JOINER_ENABLE +#endif // OPENTHREAD_CONFIG_SEEKER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE #endif // OT_CORE_MESHCOP_SEEKER_HPP_ diff --git a/tests/nexus/openthread-core-nexus-config.h b/tests/nexus/openthread-core-nexus-config.h index 644d43066..db5ad273d 100644 --- a/tests/nexus/openthread-core-nexus-config.h +++ b/tests/nexus/openthread-core-nexus-config.h @@ -118,6 +118,7 @@ #define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 0 #define OPENTHREAD_CONFIG_RADIO_STATS_ENABLE 0 #define OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 1 +#define OPENTHREAD_CONFIG_SEEKER_ENABLE 1 #define OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE 0 #define OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 1 #define OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE 0 diff --git a/tests/toranj/openthread-core-toranj-config-posix.h b/tests/toranj/openthread-core-toranj-config-posix.h index e203aad02..7324a9556 100644 --- a/tests/toranj/openthread-core-toranj-config-posix.h +++ b/tests/toranj/openthread-core-toranj-config-posix.h @@ -48,6 +48,10 @@ #define OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE 0 +#define OPENTHREAD_CONFIG_JOINER_ENABLE 0 + +#define OPENTHREAD_CONFIG_SEEKER_ENABLE 1 + #define OPENTHREAD_CONFIG_TREL_MANAGE_DNSSD_ENABLE 1 #ifdef __linux__ diff --git a/tests/toranj/openthread-core-toranj-config-simulation.h b/tests/toranj/openthread-core-toranj-config-simulation.h index 1de6eea92..f60a2d61c 100644 --- a/tests/toranj/openthread-core-toranj-config-simulation.h +++ b/tests/toranj/openthread-core-toranj-config-simulation.h @@ -71,6 +71,10 @@ #define OPENTHREAD_CONFIG_MULTICAST_DEFAULT_DNS_VERBOSE_LOGGING_STATE 0 +#define OPENTHREAD_CONFIG_JOINER_ENABLE 1 + +#define OPENTHREAD_CONFIG_SEEKER_ENABLE 1 + #define OPENTHREAD_SIMULATION_MDNS_SOCKET_IMPLEMENT_POSIX 1 #define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 0 diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h index 7a5739e5c..6bd406479 100644 --- a/tests/toranj/openthread-core-toranj-config.h +++ b/tests/toranj/openthread-core-toranj-config.h @@ -95,8 +95,6 @@ #define OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 1 -#define OPENTHREAD_CONFIG_JOINER_ENABLE 1 - #define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 1 #define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE 1