Skip to content

Commit

Permalink
[dbus] add AttachAllNodesTo API (#23) (#1046)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhanglongxia committed Oct 15, 2021
1 parent b7de451 commit bb7f533
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/dbus/client/client_error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static const std::pair<ClientError, const char *> sErrorNames[] = {
{ClientError::OT_ERROR_NOT_TMF, OTBR_OPENTHREAD_ERROR_PREFIX ".NotTmf"},
{ClientError::OT_ERROR_NOT_LOWPAN_DATA_FRAME, OTBR_OPENTHREAD_ERROR_PREFIX ".NonLowpanDatatFrame"},
{ClientError::OT_ERROR_LINK_MARGIN_LOW, OTBR_OPENTHREAD_ERROR_PREFIX ".LinkMarginLow"},
{ClientError::OT_ERROR_REJECTED, OTBR_OPENTHREAD_ERROR_PREFIX ".Rejected"},
};

ClientError ConvertFromDBusErrorName(const std::string &aErrorName)
Expand Down
6 changes: 6 additions & 0 deletions src/dbus/client/thread_api_dbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,5 +713,11 @@ void ThreadApiDBus::sHandleDBusPendingCall(DBusPendingCall *aPending, void *aThr
(api->*Handler)(aPending);
}

ClientError ThreadApiDBus::AttachAllNodesTo(const std::vector<uint8_t> &aDataset)
{
auto args = std::tie(aDataset);
return CallDBusMethodSync(OTBR_DBUS_ATTACH_ALL_NODES_TO_METHOD, args);
}

} // namespace DBus
} // namespace otbr
19 changes: 19 additions & 0 deletions src/dbus/client/thread_api_dbus.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,25 @@ class ThreadApiDBus
*/
ClientError Attach(const OtResultHandler &aHandler);

/**
* This method attaches the device to the specified Thread network.
*
* If the device has already attached to a network, send a request to migrate the existing network.
*
* @param[in] aDataset The Operational Dataset that contains parameter values of the Thread network to attach
* to. It must have a valid Delay Timer and Pending Timestamp.
*
* @retval ERROR_NONE Successfully requested the Thread network migration.
* @retval ERROR_DBUS D-Bus encode/decode error.
* @retval OT_ERROR_REJECTED The request was rejected by the leader.
* @retval OT_ERROR_FAILED Failed to send the request.
* @retval OT_ERROR_INVALID_STATE The device is attaching.
* @retval OT_ERROR_INVALID_ARGS Arguments are invalid.
* @retval OT_ERROR_BUSY There is an ongoing request.
*
*/
ClientError AttachAllNodesTo(const std::vector<uint8_t> &aDataset);

/**
* This method performs a factory reset.
*
Expand Down
1 change: 1 addition & 0 deletions src/dbus/common/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#define OTBR_DBUS_JOINER_STOP_METHOD "JoinerStop"
#define OTBR_DBUS_ADD_EXTERNAL_ROUTE_METHOD "AddExternalRoute"
#define OTBR_DBUS_REMOVE_EXTERNAL_ROUTE_METHOD "RemoveExternalRoute"
#define OTBR_DBUS_ATTACH_ALL_NODES_TO_METHOD "AttachAllNodesTo"

#define OTBR_DBUS_PROPERTY_MESH_LOCAL_PREFIX "MeshLocalPrefix"
#define OTBR_DBUS_PROPERTY_LEGACY_ULA_PREFIX "LegacyULAPrefix"
Expand Down
5 changes: 5 additions & 0 deletions src/dbus/common/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ enum class ClientError
*/
OT_ERROR_LINK_MARGIN_LOW = 34,

/**
* Request rejected.
*/
OT_ERROR_REJECTED = 37,

/**
* Generic error (should not use).
*/
Expand Down
21 changes: 21 additions & 0 deletions src/dbus/server/dbus_thread_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ otbrError DBusThreadObject::Init(void)
std::bind(&DBusThreadObject::AddExternalRouteHandler, this, _1));
RegisterMethod(OTBR_DBUS_THREAD_INTERFACE, OTBR_DBUS_REMOVE_EXTERNAL_ROUTE_METHOD,
std::bind(&DBusThreadObject::RemoveExternalRouteHandler, this, _1));
RegisterMethod(OTBR_DBUS_THREAD_INTERFACE, OTBR_DBUS_ATTACH_ALL_NODES_TO_METHOD,
std::bind(&DBusThreadObject::AttachAllNodesToHandler, this, _1));

RegisterMethod(DBUS_INTERFACE_INTROSPECTABLE, DBUS_INTROSPECT_METHOD,
std::bind(&DBusThreadObject::IntrospectHandler, this, _1));
Expand Down Expand Up @@ -291,6 +293,25 @@ void DBusThreadObject::AttachHandler(DBusRequest &aRequest)
}
}

void DBusThreadObject::AttachAllNodesToHandler(DBusRequest &aRequest)
{
std::vector<uint8_t> dataset;
otError error = OT_ERROR_NONE;

auto args = std::tie(dataset);

VerifyOrExit(DBusMessageToTuple(*aRequest.GetMessage(), args) == OTBR_ERROR_NONE, error = OT_ERROR_INVALID_ARGS);

mNcp->GetThreadHelper()->AttachAllNodesTo(dataset,
[aRequest](otError error) mutable { aRequest.ReplyOtResult(error); });

exit:
if (error != OT_ERROR_NONE)
{
aRequest.ReplyOtResult(error);
}
}

void DBusThreadObject::DetachHandler(DBusRequest &aRequest)
{
aRequest.ReplyOtResult(mNcp->GetThreadHelper()->Detach());
Expand Down
1 change: 1 addition & 0 deletions src/dbus/server/dbus_thread_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class DBusThreadObject : public DBusObject

void ScanHandler(DBusRequest &aRequest);
void AttachHandler(DBusRequest &aRequest);
void AttachAllNodesToHandler(DBusRequest &aRequest);
void DetachHandler(DBusRequest &aRequest);
void LeaveHandler(DBusRequest &aRequest);
void FactoryResetHandler(DBusRequest &aRequest);
Expand Down
1 change: 1 addition & 0 deletions src/dbus/server/error_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static const std::pair<otError, const char *> sErrorNames[] = {
{OT_ERROR_NOT_TMF, OPENTHREAD_ERROR_PREFIX ".NotTmf"},
{OT_ERROR_NOT_LOWPAN_DATA_FRAME, OPENTHREAD_ERROR_PREFIX ".NonLowpanDatatFrame"},
{OT_ERROR_LINK_MARGIN_LOW, OPENTHREAD_ERROR_PREFIX ".LinkMarginLow"},
{OT_ERROR_REJECTED, OPENTHREAD_ERROR_PREFIX ".Rejected"},
};

namespace otbr {
Expand Down
8 changes: 8 additions & 0 deletions src/dbus/server/introspect.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@
<arg name="channel_mask" type="u"/>
</method>

<!-- AttachAllNodesTo: Request to attach all nodes to the specified Thread network.
@dataset: The Operational Dataset that contains parameter values of the Thread network
to attach to. It must have a valid Delay Timer and Pending Timestamp.
-->
<method name="AttachAllNodesTo">
<arg name="dataset" type="ay"/>
</method>

<!-- Detach: Detach the current device from the Thread network. -->
<method name="Detach">
</method>
Expand Down
95 changes: 83 additions & 12 deletions src/utils/thread_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@

namespace otbr {
namespace agent {

ThreadHelper::ThreadHelper(otInstance *aInstance, otbr::Ncp::ControllerOpenThread *aNcp)
: mInstance(aInstance)
, mNcp(aNcp)
Expand Down Expand Up @@ -98,7 +97,7 @@ void ThreadHelper::Scan(ScanHandler aHandler)
mScanResults.clear();

error =
otLinkActiveScan(mInstance, /*scanChannels =*/0, /*scanDuration=*/0, &ThreadHelper::sActiveScanHandler, this);
otLinkActiveScan(mInstance, /*scanChannels =*/0, /*scanDuration=*/0, &ThreadHelper::ActiveScanHandler, this);

exit:
if (error != OT_ERROR_NONE)
Expand All @@ -122,7 +121,7 @@ void ThreadHelper::RandomFill(void *aBuf, size_t size)
}
}

void ThreadHelper::sActiveScanHandler(otActiveScanResult *aResult, void *aThreadHelper)
void ThreadHelper::ActiveScanHandler(otActiveScanResult *aResult, void *aThreadHelper)
{
ThreadHelper *helper = static_cast<ThreadHelper *>(aThreadHelper);

Expand Down Expand Up @@ -193,7 +192,6 @@ void ThreadHelper::Attach(const std::string & aNetworkName,

VerifyOrExit(aHandler != nullptr, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = OT_ERROR_INVALID_STATE);
mAttachHandler = aHandler;
VerifyOrExit(aNetworkKey.empty() || aNetworkKey.size() == sizeof(networkKey.m8), error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(aPSKc.empty() || aPSKc.size() == sizeof(pskc.m8), error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(aChannelMask != 0, error = OT_ERROR_INVALID_ARGS);
Expand Down Expand Up @@ -259,14 +257,15 @@ void ThreadHelper::Attach(const std::string & aNetworkName,
SuccessOrExit(error = otThreadSetPskc(mInstance, &pskc));

SuccessOrExit(error = otThreadSetEnabled(mInstance, true));
mAttachHandler = aHandler;

exit:
if (error != OT_ERROR_NONE)
{
if (aHandler)
{
aHandler(error);
}
mAttachHandler = nullptr;
}
}

Expand All @@ -275,13 +274,13 @@ void ThreadHelper::Attach(ResultHandler aHandler)
otError error = OT_ERROR_NONE;

VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = OT_ERROR_INVALID_STATE);
mAttachHandler = aHandler;

if (!otIp6IsEnabled(mInstance))
{
SuccessOrExit(error = otIp6SetEnabled(mInstance, true));
}
SuccessOrExit(error = otThreadSetEnabled(mInstance, true));
mAttachHandler = aHandler;

exit:
if (error != OT_ERROR_NONE)
Expand All @@ -290,7 +289,6 @@ void ThreadHelper::Attach(ResultHandler aHandler)
{
aHandler(error);
}
mAttachHandler = nullptr;
}
}

Expand Down Expand Up @@ -325,26 +323,27 @@ void ThreadHelper::JoinerStart(const std::string &aPskd,

VerifyOrExit(aHandler != nullptr, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = OT_ERROR_INVALID_STATE);
mJoinerHandler = aHandler;

if (!otIp6IsEnabled(mInstance))
{
SuccessOrExit(error = otIp6SetEnabled(mInstance, true));
}
error = otJoinerStart(mInstance, aPskd.c_str(), aProvisioningUrl.c_str(), aVendorName.c_str(), aVendorModel.c_str(),
aVendorSwVersion.c_str(), aVendorData.c_str(), sJoinerCallback, this);
SuccessOrExit(error = otJoinerStart(mInstance, aPskd.c_str(), aProvisioningUrl.c_str(), aVendorName.c_str(),
aVendorModel.c_str(), aVendorSwVersion.c_str(), aVendorData.c_str(),
JoinerCallback, this));
mJoinerHandler = aHandler;

exit:
if (error != OT_ERROR_NONE)
{
if (aHandler)
{
aHandler(error);
}
mJoinerHandler = nullptr;
}
}

void ThreadHelper::sJoinerCallback(otError aError, void *aThreadHelper)
void ThreadHelper::JoinerCallback(otError aError, void *aThreadHelper)
{
ThreadHelper *helper = static_cast<ThreadHelper *>(aThreadHelper);

Expand Down Expand Up @@ -399,6 +398,78 @@ void ThreadHelper::LogOpenThreadResult(const char *aAction, otError aError)
}
}

void ThreadHelper::AttachAllNodesTo(const std::vector<uint8_t> &aDatasetTlvs, ResultHandler aHandler)
{
otError error = OT_ERROR_NONE;
otOperationalDataset emptyDataset{};
otDeviceRole role = otThreadGetDeviceRole(mInstance);

assert(aHandler != nullptr);
VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = OT_ERROR_BUSY);

if (role == OT_DEVICE_ROLE_DISABLED || role == OT_DEVICE_ROLE_DETACHED)
{
otOperationalDataset existingDataset;

error = otDatasetGetActive(mInstance, &existingDataset);
VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_NOT_FOUND);

VerifyOrExit(error == OT_ERROR_NOT_FOUND, error = OT_ERROR_INVALID_STATE);

otOperationalDatasetTlvs datasetTlvs;

VerifyOrExit(aDatasetTlvs.size() <= sizeof(datasetTlvs.mTlvs), error = OT_ERROR_INVALID_ARGS);
std::copy(aDatasetTlvs.begin(), aDatasetTlvs.end(), datasetTlvs.mTlvs);
datasetTlvs.mLength = aDatasetTlvs.size();

SuccessOrExit(error = otDatasetSetActiveTlvs(mInstance, &datasetTlvs));

if (!otIp6IsEnabled(mInstance))
{
SuccessOrExit(error = otIp6SetEnabled(mInstance, true));
}
SuccessOrExit(error = otThreadSetEnabled(mInstance, true));

aHandler(OT_ERROR_NONE);
ExitNow();
}

SuccessOrExit(error = otDatasetSendMgmtPendingSet(mInstance, &emptyDataset, aDatasetTlvs.data(),
aDatasetTlvs.size(), MgmtSetResponseHandler, this));
mAttachHandler = aHandler;

exit:
if (error != OT_ERROR_NONE)
{
aHandler(error);
}
}

void ThreadHelper::MgmtSetResponseHandler(otError aResult, void *aContext)
{
static_cast<ThreadHelper *>(aContext)->MgmtSetResponseHandler(aResult);
}

void ThreadHelper::MgmtSetResponseHandler(otError aResult)
{
LogOpenThreadResult("MgmtSetResponseHandler()", aResult);

assert(mAttachHandler != nullptr);

switch (aResult)
{
case OT_ERROR_NONE:
case OT_ERROR_REJECTED:
break;
default:
aResult = OT_ERROR_FAILED;
break;
}

mAttachHandler(aResult);
mAttachHandler = nullptr;
}

#if OTBR_ENABLE_UNSECURE_JOIN
otError ThreadHelper::PermitUnsecureJoin(uint16_t aPort, uint32_t aSeconds)
{
Expand Down
16 changes: 14 additions & 2 deletions src/utils/thread_helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ class ThreadHelper
*/
void Attach(ResultHandler aHandler);

/**
* This method makes all nodes in the current network attach to the network specified by the dataset TLVs.
*
* @param[in] aDatasetTlvs The dataset TLVs.
* @param[in] aHandler The result handler.
*
*/
void AttachAllNodesTo(const std::vector<uint8_t> &aDatasetTlvs, ResultHandler aHandler);

/**
* This method resets the OpenThread stack.
*
Expand Down Expand Up @@ -208,12 +217,15 @@ class ThreadHelper
static void LogOpenThreadResult(const char *aAction, otError aError);

private:
static void sActiveScanHandler(otActiveScanResult *aResult, void *aThreadHelper);
static void ActiveScanHandler(otActiveScanResult *aResult, void *aThreadHelper);
void ActiveScanHandler(otActiveScanResult *aResult);

static void sJoinerCallback(otError aError, void *aThreadHelper);
static void JoinerCallback(otError aError, void *aThreadHelper);
void JoinerCallback(otError aResult);

static void MgmtSetResponseHandler(otError aResult, void *aContext);
void MgmtSetResponseHandler(otError aResult);

void RandomFill(void *aBuf, size_t size);
uint8_t RandomChannelFromChannelMask(uint32_t aChannelMask);

Expand Down
2 changes: 1 addition & 1 deletion tests/dbus/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ add_test(
set_tests_properties(dbus-client PROPERTIES
ENVIRONMENT CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}
)
set_tests_properties(dbus-client PROPERTIES TIMEOUT 120)
set_tests_properties(dbus-client PROPERTIES TIMEOUT 420)
Loading

0 comments on commit bb7f533

Please sign in to comment.