mirror of
https://github.com/espressif/openthread.git
synced 2026-08-16 07:37:47 +00:00
[core] add OffsetRange class (#10436)
This commit introduces the `OffsetRange` class, which represents a range of offsets within a `Message` or data buffer (i.e., a starting offset and a length indicating the number of bytes in the range). The class provides methods for common operations: - Getting the start or end offset, or the remaining length. - Checking if the range is empty or contains a certain number of bytes. - Advancing the start offset by a given amount, ensuring it never goes beyond the end offset. - Shrinking the range's length. The new `OffsetRange` class simplifies methods that previously used separate `aOffset` and `aLength` input parameters, improving code readability and maintainability. It also facilitates reading and processing content within a specified range. For example, `Tlv::FindTlvValueOffsetRange()` now directly returns an `OffsetRange` indicating the location of the TLV value. The `Message` class is also updated with new `Read()` and `Append()` method variants that accept `OffsetRange` arguments. These methods ensure that read content is contained within the specified `OffsetRange`.
This commit is contained in:
@@ -432,6 +432,8 @@ openthread_core_files = [
|
||||
"common/notifier.hpp",
|
||||
"common/num_utils.hpp",
|
||||
"common/numeric_limits.hpp",
|
||||
"common/offset_range.cpp",
|
||||
"common/offset_range.hpp",
|
||||
"common/owned_ptr.hpp",
|
||||
"common/owning_list.hpp",
|
||||
"common/pool.hpp",
|
||||
|
||||
@@ -112,6 +112,7 @@ set(COMMON_SOURCES
|
||||
common/log.cpp
|
||||
common/message.cpp
|
||||
common/notifier.cpp
|
||||
common/offset_range.cpp
|
||||
common/preference.cpp
|
||||
common/random.cpp
|
||||
common/settings.cpp
|
||||
|
||||
@@ -149,7 +149,7 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Message &aMessage,
|
||||
ThreadStatusTlv::MlrStatus status = ThreadStatusTlv::kMlrSuccess;
|
||||
Config config;
|
||||
|
||||
uint16_t addressesOffset, addressesLength;
|
||||
OffsetRange offsetRange;
|
||||
Ip6::Address address;
|
||||
Ip6::Address addresses[Ip6AddressesTlv::kMaxAddresses];
|
||||
uint8_t failedAddressNum = 0;
|
||||
@@ -188,11 +188,10 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Message &aMessage,
|
||||
|
||||
processTimeoutTlv = hasCommissionerSessionIdTlv && (Tlv::Find<ThreadTimeoutTlv>(aMessage, timeout) == kErrorNone);
|
||||
|
||||
VerifyOrExit(Tlv::FindTlvValueOffset(aMessage, Ip6AddressesTlv::kIp6Addresses, addressesOffset, addressesLength) ==
|
||||
kErrorNone,
|
||||
VerifyOrExit(Tlv::FindTlvValueOffsetRange(aMessage, Ip6AddressesTlv::kIp6Addresses, offsetRange) == kErrorNone,
|
||||
error = kErrorParse);
|
||||
VerifyOrExit(addressesLength % sizeof(Ip6::Address) == 0, status = ThreadStatusTlv::kMlrGeneralFailure);
|
||||
VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses,
|
||||
VerifyOrExit(offsetRange.GetLength() % sizeof(Ip6::Address) == 0, status = ThreadStatusTlv::kMlrGeneralFailure);
|
||||
VerifyOrExit(offsetRange.GetLength() / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses,
|
||||
status = ThreadStatusTlv::kMlrGeneralFailure);
|
||||
|
||||
if (!processTimeoutTlv)
|
||||
@@ -220,9 +219,10 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Message &aMessage,
|
||||
|
||||
expireTime = TimerMilli::GetNow() + TimeMilli::SecToMsec(timeout);
|
||||
|
||||
for (uint16_t offset = 0; offset < addressesLength; offset += sizeof(Ip6::Address))
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
IgnoreError(aMessage.Read(addressesOffset + offset, address));
|
||||
IgnoreError(aMessage.Read(offsetRange, address));
|
||||
offsetRange.AdvanceOffset(sizeof(Ip6::Address));
|
||||
|
||||
if (timeout == 0)
|
||||
{
|
||||
@@ -581,7 +581,7 @@ template <> void Manager::HandleTmf<kUriBackboneAnswer>(Coap::Message &aMessage,
|
||||
bool proactive;
|
||||
Ip6::Address dua;
|
||||
Ip6::InterfaceIdentifier meshLocalIid;
|
||||
uint16_t networkNameOffset, networkNameLength;
|
||||
OffsetRange offsetRange;
|
||||
uint32_t timeSinceLastTransaction;
|
||||
uint16_t srcRloc16 = Mle::kInvalidRloc16;
|
||||
|
||||
@@ -595,9 +595,7 @@ template <> void Manager::HandleTmf<kUriBackboneAnswer>(Coap::Message &aMessage,
|
||||
SuccessOrExit(error = Tlv::Find<ThreadTargetTlv>(aMessage, dua));
|
||||
SuccessOrExit(error = Tlv::Find<ThreadMeshLocalEidTlv>(aMessage, meshLocalIid));
|
||||
SuccessOrExit(error = Tlv::Find<ThreadLastTransactionTimeTlv>(aMessage, timeSinceLastTransaction));
|
||||
|
||||
SuccessOrExit(error =
|
||||
Tlv::FindTlvValueOffset(aMessage, ThreadTlv::kNetworkName, networkNameOffset, networkNameLength));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, ThreadTlv::kNetworkName, offsetRange));
|
||||
|
||||
error = Tlv::Find<ThreadRloc16Tlv>(aMessage, srcRloc16);
|
||||
VerifyOrExit(error == kErrorNone || error == kErrorNotFound);
|
||||
|
||||
@@ -412,6 +412,11 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Message::AppendBytesFromMessage(const Message &aMessage, const OffsetRange &aOffsetRange)
|
||||
{
|
||||
return AppendBytesFromMessage(aMessage, aOffsetRange.GetOffset(), aOffsetRange.GetLength());
|
||||
}
|
||||
|
||||
Error Message::AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -649,11 +654,27 @@ uint16_t Message::ReadBytes(uint16_t aOffset, void *aBuf, uint16_t aLength) cons
|
||||
return static_cast<uint16_t>(bufPtr - reinterpret_cast<uint8_t *>(aBuf));
|
||||
}
|
||||
|
||||
uint16_t Message::ReadBytes(const OffsetRange &aOffsetRange, void *aBuf) const
|
||||
{
|
||||
return ReadBytes(aOffsetRange.GetOffset(), aBuf, aOffsetRange.GetLength());
|
||||
}
|
||||
|
||||
Error Message::Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const
|
||||
{
|
||||
return (ReadBytes(aOffset, aBuf, aLength) == aLength) ? kErrorNone : kErrorParse;
|
||||
}
|
||||
|
||||
Error Message::Read(const OffsetRange &aOffsetRange, void *aBuf, uint16_t aLength) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(aOffsetRange.Contains(aLength), error = kErrorParse);
|
||||
VerifyOrExit(ReadBytes(aOffsetRange.GetOffset(), aBuf, aLength) == aLength, error = kErrorParse);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool Message::CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher) const
|
||||
{
|
||||
uint16_t bytesToCompare = aLength;
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "common/linked_list.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/non_copyable.hpp"
|
||||
#include "common/offset_range.hpp"
|
||||
#include "common/pool.hpp"
|
||||
#include "common/timer.hpp"
|
||||
#include "common/type_traits.hpp"
|
||||
@@ -707,6 +708,19 @@ public:
|
||||
*/
|
||||
Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Appends bytes read from another or potentially the same message to the end of the current message.
|
||||
*
|
||||
* @param[in] aMessage The message to read the bytes from (it can be the same as the current message).
|
||||
* @param[in] aOffsetRange The offset range in @p aMessage to read bytes from.
|
||||
*
|
||||
* @retval kErrorNone Successfully appended the bytes.
|
||||
* @retval kErrorNoBufs Insufficient available buffers to grow the message.
|
||||
* @retval kErrorParse Not enough bytes in @p aMessage to read @p aOffsetRange.
|
||||
*
|
||||
*/
|
||||
Error AppendBytesFromMessage(const Message &aMessage, const OffsetRange &aOffsetRange);
|
||||
|
||||
/**
|
||||
* Appends an object to the end of the message.
|
||||
*
|
||||
@@ -757,6 +771,17 @@ public:
|
||||
*/
|
||||
uint16_t ReadBytes(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
|
||||
|
||||
/**
|
||||
* Reads bytes from the message.
|
||||
*
|
||||
* @param[in] aOffsetRange The offset range in the message to read bytes from.
|
||||
* @param[out] aBuf A pointer to a data buffer to copy the read bytes into.
|
||||
*
|
||||
* @returns The number of bytes read.
|
||||
*
|
||||
*/
|
||||
uint16_t ReadBytes(const OffsetRange &aOffsetRange, void *aBuf) const;
|
||||
|
||||
/**
|
||||
* Reads a given number of bytes from the message.
|
||||
*
|
||||
@@ -773,6 +798,22 @@ public:
|
||||
*/
|
||||
Error Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
|
||||
|
||||
/**
|
||||
* Reads a given number of bytes from the message.
|
||||
*
|
||||
* If there are fewer bytes available in the message or @p aOffsetRange than the requested @p aLength, the
|
||||
* available bytes are read and copied into @p aBuf. In this case `kErrorParse` will be returned.
|
||||
*
|
||||
* @param[in] aOffsetRange The offset range in the message to read from.
|
||||
* @param[out] aBuf A pointer to a data buffer to copy the read bytes into.
|
||||
* @param[in] aLength Number of bytes to read.
|
||||
*
|
||||
* @retval kErrorNone Requested bytes were successfully read from message.
|
||||
* @retval kErrorParse Not enough bytes remaining to read the requested @p aLength.
|
||||
*
|
||||
*/
|
||||
Error Read(const OffsetRange &aOffsetRange, void *aBuf, uint16_t aLength) const;
|
||||
|
||||
/**
|
||||
* Reads an object from the message.
|
||||
*
|
||||
@@ -796,6 +837,29 @@ public:
|
||||
return Read(aOffset, &aObject, sizeof(ObjectType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an object from the message.
|
||||
*
|
||||
* If there are fewer bytes available in the message or @p aOffsetRange than the requested object size, the
|
||||
* available bytes will be read and copied into @p aObject (@p aObject will be read partially). In this case
|
||||
* `kErrorParse` will be returned.
|
||||
*
|
||||
* @tparam ObjectType The object type to read from the message.
|
||||
*
|
||||
* @param[in] aOffsetRange The offset range in the message to read from.
|
||||
* @param[out] aObject A reference to the object to read into.
|
||||
*
|
||||
* @retval kErrorNone Object @p aObject was successfully read from message.
|
||||
* @retval kErrorParse Not enough bytes remaining in message to read the entire object.
|
||||
*
|
||||
*/
|
||||
template <typename ObjectType> Error Read(const OffsetRange &aOffsetRange, ObjectType &aObject) const
|
||||
{
|
||||
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
|
||||
|
||||
return Read(aOffsetRange, &aObject, sizeof(ObjectType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the bytes in the message at a given offset with a given byte array.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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 helper method for an offset range.
|
||||
*/
|
||||
|
||||
#include "offset_range.hpp"
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/message.hpp"
|
||||
#include "common/num_utils.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
void OffsetRange::Init(uint16_t aOffset, uint16_t aLength)
|
||||
{
|
||||
uint16_t maxLength = NumericLimits<uint16_t>::kMax - aOffset;
|
||||
|
||||
mOffset = aOffset;
|
||||
mLength = Min(aLength, maxLength);
|
||||
}
|
||||
|
||||
void OffsetRange::InitFromRange(uint16_t aStartOffset, uint16_t aEndOffset)
|
||||
{
|
||||
Init(aStartOffset, Max(aStartOffset, aEndOffset) - aStartOffset);
|
||||
}
|
||||
|
||||
void OffsetRange::InitFromMessageOffsetToEnd(const Message &aMessage)
|
||||
{
|
||||
InitFromRange(aMessage.GetOffset(), aMessage.GetLength());
|
||||
}
|
||||
|
||||
void OffsetRange::InitFromMessageFullLength(const Message &aMessage) { Init(0, aMessage.GetLength()); }
|
||||
|
||||
void OffsetRange::AdvanceOffset(uint32_t aLength)
|
||||
{
|
||||
uint16_t length = static_cast<uint16_t>(Min<uint32_t>(aLength, mLength));
|
||||
|
||||
mOffset += length;
|
||||
mLength -= length;
|
||||
}
|
||||
|
||||
void OffsetRange::ShrinkLength(uint16_t aLength) { mLength = Min(mLength, aLength); }
|
||||
|
||||
} // namespace ot
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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 an offset range.
|
||||
*/
|
||||
|
||||
#ifndef OFFSET_RANGE_HPP_
|
||||
#define OFFSET_RANGE_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common/clearable.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
class Message;
|
||||
|
||||
/**
|
||||
* Represents an offset range.
|
||||
*
|
||||
*/
|
||||
class OffsetRange : public Clearable<OffsetRange>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes the `OffsetRange`.
|
||||
*
|
||||
* @param[in] aOffset The start offset.
|
||||
* @param[in] aLength The range length (number of bytes).
|
||||
*
|
||||
*/
|
||||
void Init(uint16_t aOffset, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Initializes the `OffsetRange` from given start and end offsets.
|
||||
*
|
||||
* The range is inclusive of the start offset (@p aStartOffset) but exclusive of the end offset (@p aEndOffset).
|
||||
*
|
||||
* @param[in] aStartOffset The start offset (inclusive).
|
||||
* @param[in] aEndOffset The end offset (exclusive).
|
||||
*
|
||||
*/
|
||||
void InitFromRange(uint16_t aStartOffset, uint16_t aEndOffset);
|
||||
|
||||
/**
|
||||
* Initializes the `OffsetRange` from a given `Message` from its offset to the message end.
|
||||
*
|
||||
* The start offset of the range is set to `aMessage.GetOffset()`, and the end offset is set to include all bytes
|
||||
* in the message up to its current length `aMessage.GetLength()`.
|
||||
*
|
||||
* @param[in] aMessage The `Message` to initialize the `OffsetRange` from.
|
||||
*
|
||||
*/
|
||||
void InitFromMessageOffsetToEnd(const Message &aMessage);
|
||||
|
||||
/**
|
||||
* Initializes the `OffsetRange` from a given `Message` from zero offset up to to its full length.
|
||||
*
|
||||
* The start offset of the range is set to zero, and the end offset is set to include full length of @p aMessage.
|
||||
*
|
||||
* @param[in] aMessage The `Message` to initialize the `OffsetRange` from.
|
||||
*
|
||||
*/
|
||||
void InitFromMessageFullLength(const Message &aMessage);
|
||||
|
||||
/**
|
||||
* Gets the start offset of the `OffsetRange`
|
||||
*
|
||||
* @returns The start offset.
|
||||
*
|
||||
*/
|
||||
uint16_t GetOffset(void) const { return mOffset; }
|
||||
|
||||
/**
|
||||
* Gets the end offset of the `OffsetRange`.
|
||||
*
|
||||
* This offset is exclusive, meaning it marks the position immediately after the last byte within the range.
|
||||
*
|
||||
* @returns The end offset.
|
||||
*
|
||||
*/
|
||||
uint16_t GetEndOffset(void) const { return (mOffset + mLength); }
|
||||
|
||||
/**
|
||||
* Gets the `OffsetRange` length.
|
||||
*
|
||||
* @returns The length of the `OffsetRange` in bytes.
|
||||
*
|
||||
*/
|
||||
uint16_t GetLength(void) const { return mLength; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the `OffsetRange` is empty.
|
||||
*
|
||||
* @retval TRUE The `OffsetRange` is empty.
|
||||
* @retval FALSE The `OffsetRange` is not empty (contains at least one byte).
|
||||
*
|
||||
*/
|
||||
bool IsEmpty(void) const { return (mLength == 0); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the `OffsetRange` contains a given number of bytes.
|
||||
*
|
||||
* @param[in] aLength The length to check.
|
||||
*
|
||||
* @retval TRUE The `OffsetRange` contains @p aLength or more bytes.
|
||||
* @retval FALSE The `OffsetRange` does not contain @p aLength bytes.
|
||||
*
|
||||
*/
|
||||
bool Contains(uint32_t aLength) const { return aLength <= mLength; }
|
||||
|
||||
/**
|
||||
* Advances the start offset forward by the given number of bytes.
|
||||
*
|
||||
* This method ensures the start offset does not go beyond the end offset of the `OffsetRange`. If @p aLength is
|
||||
* greater than the available bytes in the `OffsetRange`, the start offset is adjusted to the end offset,
|
||||
* effectively shrinking the range to zero length.
|
||||
*
|
||||
* @param[in] aLength The number of bytes to advance the start offset.
|
||||
*
|
||||
*/
|
||||
void AdvanceOffset(uint32_t aLength);
|
||||
|
||||
/**
|
||||
* Shrinks the `OffsetRange` length to a given length.
|
||||
*
|
||||
* If the current length of the `OffsetRange` is longer than @p aLength, the offset range is shortened to
|
||||
* @p aLength. If the range is already shorter or the same, it remains unchanged.
|
||||
*
|
||||
* @param[in] aLength The new length to use.
|
||||
*
|
||||
*/
|
||||
void ShrinkLength(uint16_t aLength);
|
||||
|
||||
private:
|
||||
uint16_t mOffset;
|
||||
uint16_t mLength;
|
||||
};
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OFFSET_RANGE_HPP_
|
||||
+11
-34
@@ -56,19 +56,15 @@ const uint8_t *Tlv::GetValue(void) const
|
||||
|
||||
Error Tlv::AppendTo(Message &aMessage) const { return aMessage.AppendBytes(this, static_cast<uint16_t>(GetSize())); }
|
||||
|
||||
Error Tlv::ParseAndSkipTlv(const Message &aMessage, uint16_t &aOffset)
|
||||
Error Tlv::ParseAndSkipTlv(const Message &aMessage, OffsetRange &aOffsetRange)
|
||||
{
|
||||
Error error;
|
||||
ParsedInfo info;
|
||||
|
||||
SuccessOrExit(error = info.ParseFrom(aMessage, aOffset));
|
||||
SuccessOrExit(error = info.ParseFrom(aMessage, aOffsetRange.GetOffset()));
|
||||
|
||||
// `ParseFrom()` has already validated that the entire TLV is
|
||||
// present within `aMessage`. This ensures that `aOffset + mSize`
|
||||
// is less than `aMessage.GetLength()`, and therefore we cannot
|
||||
// have an overflow here.
|
||||
|
||||
aOffset += info.mSize;
|
||||
VerifyOrExit(aOffsetRange.Contains(info.mSize), error = kErrorParse);
|
||||
aOffsetRange.AdvanceOffset(info.mSize);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -99,32 +95,15 @@ Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tl
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
Error Tlv::FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength)
|
||||
|
||||
Error Tlv::FindTlvValueOffsetRange(const Message &aMessage, uint8_t aType, OffsetRange &aOffsetRange)
|
||||
{
|
||||
Error error;
|
||||
ParsedInfo info;
|
||||
|
||||
SuccessOrExit(error = info.FindIn(aMessage, aType));
|
||||
|
||||
aValueOffset = info.mValueOffset;
|
||||
aLength = info.mLength;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Tlv::FindTlvValueStartEndOffsets(const Message &aMessage,
|
||||
uint8_t aType,
|
||||
uint16_t &aValueStartOffset,
|
||||
uint16_t &aValueEndOffset)
|
||||
{
|
||||
Error error;
|
||||
ParsedInfo info;
|
||||
|
||||
SuccessOrExit(error = info.FindIn(aMessage, aType));
|
||||
|
||||
aValueStartOffset = info.mValueOffset;
|
||||
aValueEndOffset = info.mValueOffset + info.mLength;
|
||||
aOffsetRange.Init(info.mValueOffset, info.mLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -291,13 +270,11 @@ template Error Tlv::FindUintTlv<uint32_t>(const Message &aMessage, uint8_t aType
|
||||
|
||||
Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint16_t aLength)
|
||||
{
|
||||
Error error;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
Error error;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
SuccessOrExit(error = FindTlvValueOffset(aMessage, aType, offset, length));
|
||||
VerifyOrExit(length >= aLength, error = kErrorParse);
|
||||
aMessage.ReadBytes(offset, aValue, aLength);
|
||||
SuccessOrExit(error = FindTlvValueOffsetRange(aMessage, aType, offsetRange));
|
||||
error = aMessage.Read(offsetRange, aValue, aLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
+10
-29
@@ -42,6 +42,7 @@
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "common/offset_range.hpp"
|
||||
#include "common/type_traits.hpp"
|
||||
|
||||
namespace ot {
|
||||
@@ -245,19 +246,19 @@ public:
|
||||
// Static methods for reading/finding/appending TLVs in a `Message`.
|
||||
|
||||
/**
|
||||
* Parses a TLV in a message at a given offset, validating that it is fully contained within the message and then
|
||||
* updating the offset to skip over the entire parsed TLV.
|
||||
* Parses a TLV in a message from a given offset range, validating that it is fully contained within the offset
|
||||
* range and the message, and then updating the offset range to skip over the entire parsed TLV.
|
||||
*
|
||||
* Can be used independent of whether the read TLV (from the message) is an Extended TLV or not.
|
||||
*
|
||||
* @param[in] aMessage The message to read from.
|
||||
* @param[in,out] aOffset The offset to read from. On success, it is updated to point after the parsed TLV.
|
||||
* @param[in] aMessage The message to read from.
|
||||
* @param[in,out] aOffsetRange The offset range to read from. On success, it is updated to skip the TLV.
|
||||
*
|
||||
* @retval kErrorNone Successfully parsed a TLV from @p aMessage. @p aOffset is updated.
|
||||
* @retval kErrorNone Successfully parsed a TLV from @p aMessage. @p aOffsetRange is updated.
|
||||
* @retval kErrorParse The TLV was not well-formed or was not fully contained in @p aMessage.
|
||||
*
|
||||
*/
|
||||
static Error ParseAndSkipTlv(const Message &aMessage, uint16_t &aOffset);
|
||||
static Error ParseAndSkipTlv(const Message &aMessage, OffsetRange &aOffsetRange);
|
||||
|
||||
/**
|
||||
* Reads a TLV's value in a message at a given offset expecting a minimum length for the value.
|
||||
@@ -405,39 +406,19 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the offset and length of TLV value for a given TLV type within @p aMessage.
|
||||
* Finds the offset range of the TLV value for a given TLV type within @p aMessage.
|
||||
*
|
||||
* Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
* @param[in] aType The Type value to search for.
|
||||
* @param[out] aValueOffset The offset where the value starts.
|
||||
* @param[out] aLength The length of the value.
|
||||
* @param[out] aOffsetRange A reference to return the offset range of the TLV value when found.
|
||||
*
|
||||
* @retval kErrorNone Successfully found the TLV.
|
||||
* @retval kErrorNotFound Could not find the TLV with Type @p aType.
|
||||
*
|
||||
*/
|
||||
static Error FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength);
|
||||
|
||||
/**
|
||||
* Finds the start and end offset of TLV value for a given TLV type with @p aMessage.
|
||||
*
|
||||
* Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
* @param[in] aType The Type value to search for.
|
||||
* @param[out] aValueStartOffset The offset where the value starts.
|
||||
* @param[out] aValueEndOffset The offset immediately after the last byte of value.
|
||||
*
|
||||
* @retval kErrorNone Successfully found the TLV.
|
||||
* @retval kErrorNotFound Could not find the TLV with Type @p aType.
|
||||
*
|
||||
*/
|
||||
static Error FindTlvValueStartEndOffsets(const Message &aMessage,
|
||||
uint8_t aType,
|
||||
uint16_t &aValueStartOffset,
|
||||
uint16_t &aValueEndOffset);
|
||||
static Error FindTlvValueOffsetRange(const Message &aMessage, uint8_t aType, OffsetRange &aOffsetRange);
|
||||
|
||||
/**
|
||||
* Searches for a TLV with a given type in a message, ensures its length is same or larger than
|
||||
|
||||
@@ -317,22 +317,20 @@ template <> void BorderAgent::HandleTmf<kUriProxyTx>(Coap::Message &aMessage, co
|
||||
Error error = kErrorNone;
|
||||
Message *message = nullptr;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
OffsetRange offsetRange;
|
||||
UdpEncapsulationTlvHeader udpEncapHeader;
|
||||
|
||||
VerifyOrExit(mState != kStateStopped);
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Tlv::kUdpEncapsulation, offset, length));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kUdpEncapsulation, offsetRange));
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(offset, udpEncapHeader));
|
||||
offset += sizeof(UdpEncapsulationTlvHeader);
|
||||
length -= sizeof(UdpEncapsulationTlvHeader);
|
||||
SuccessOrExit(error = aMessage.Read(offsetRange, udpEncapHeader));
|
||||
offsetRange.AdvanceOffset(sizeof(UdpEncapsulationTlvHeader));
|
||||
|
||||
VerifyOrExit(udpEncapHeader.GetSourcePort() > 0 && udpEncapHeader.GetDestinationPort() > 0, error = kErrorDrop);
|
||||
|
||||
VerifyOrExit((message = Get<Ip6::Udp>().NewMessage()) != nullptr, error = kErrorNoBufs);
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offset, length));
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
|
||||
|
||||
messageInfo.SetSockPort(udpEncapHeader.GetSourcePort());
|
||||
messageInfo.SetSockAddr(mCommissionerAloc.GetAddress());
|
||||
@@ -376,16 +374,18 @@ bool BorderAgent::HandleUdpReceive(const Message &aMessage, const Ip6::MessageIn
|
||||
{
|
||||
ExtendedTlv extTlv;
|
||||
UdpEncapsulationTlvHeader udpEncapHeader;
|
||||
uint16_t udpLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
OffsetRange offsetRange;
|
||||
|
||||
offsetRange.InitFromMessageOffsetToEnd(aMessage);
|
||||
|
||||
extTlv.SetType(Tlv::kUdpEncapsulation);
|
||||
extTlv.SetLength(sizeof(UdpEncapsulationTlvHeader) + udpLength);
|
||||
extTlv.SetLength(sizeof(UdpEncapsulationTlvHeader) + offsetRange.GetLength());
|
||||
SuccessOrExit(error = message->Append(extTlv));
|
||||
|
||||
udpEncapHeader.SetSourcePort(aMessageInfo.GetPeerPort());
|
||||
udpEncapHeader.SetDestinationPort(aMessageInfo.GetSockPort());
|
||||
SuccessOrExit(error = message->Append(udpEncapHeader));
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, aMessage.GetOffset(), udpLength));
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = Tlv::Append<Ip6AddressTlv>(*message, aMessageInfo.GetPeerAddr()));
|
||||
@@ -427,10 +427,12 @@ exit:
|
||||
|
||||
Error BorderAgent::ForwardToCommissioner(Coap::Message &aForwardMessage, const Message &aMessage)
|
||||
{
|
||||
Error error;
|
||||
Error error;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
offsetRange.InitFromMessageOffsetToEnd(aMessage);
|
||||
SuccessOrExit(error = aForwardMessage.AppendBytesFromMessage(aMessage, offsetRange));
|
||||
|
||||
SuccessOrExit(error = aForwardMessage.AppendBytesFromMessage(aMessage, aMessage.GetOffset(),
|
||||
aMessage.GetLength() - aMessage.GetOffset()));
|
||||
SuccessOrExit(error = SendMessage(aForwardMessage));
|
||||
|
||||
LogInfo("Sent to commissioner");
|
||||
@@ -498,6 +500,7 @@ template <> void BorderAgent::HandleTmf<kUriRelayTx>(Coap::Message &aMessage, co
|
||||
uint16_t joinerRouterRloc;
|
||||
Coap::Message *message = nullptr;
|
||||
Tmf::MessageInfo messageInfo(GetInstance());
|
||||
OffsetRange offsetRange;
|
||||
|
||||
VerifyOrExit(mState != kStateStopped);
|
||||
|
||||
@@ -508,8 +511,8 @@ template <> void BorderAgent::HandleTmf<kUriRelayTx>(Coap::Message &aMessage, co
|
||||
message = Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(kUriRelayTx);
|
||||
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, aMessage.GetOffset(),
|
||||
aMessage.GetLength() - aMessage.GetOffset()));
|
||||
offsetRange.InitFromMessageOffsetToEnd(aMessage);
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
|
||||
|
||||
messageInfo.SetSockAddrToRlocPeerAddrTo(joinerRouterRloc);
|
||||
messageInfo.SetSockPortToTmf();
|
||||
@@ -531,6 +534,7 @@ Error BorderAgent::ForwardToLeader(const Coap::Message &aMessage, const Ip6::Mes
|
||||
Coap::Message *message = nullptr;
|
||||
bool petition = false;
|
||||
bool separate = false;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
VerifyOrExit(mState != kStateStopped);
|
||||
|
||||
@@ -558,8 +562,8 @@ Error BorderAgent::ForwardToLeader(const Coap::Message &aMessage, const Ip6::Mes
|
||||
message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(aUri);
|
||||
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, aMessage.GetOffset(),
|
||||
aMessage.GetLength() - aMessage.GetOffset()));
|
||||
offsetRange.InitFromMessageOffsetToEnd(aMessage);
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
|
||||
|
||||
messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc();
|
||||
messageInfo.SetSockPortToTmf();
|
||||
|
||||
@@ -902,8 +902,7 @@ template <> void Commissioner::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, c
|
||||
Ip6::InterfaceIdentifier joinerIid;
|
||||
uint16_t joinerRloc;
|
||||
Ip6::MessageInfo joinerMessageInfo;
|
||||
uint16_t startOffset;
|
||||
uint16_t endOffset;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
|
||||
|
||||
@@ -913,8 +912,7 @@ template <> void Commissioner::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, c
|
||||
SuccessOrExit(error = Tlv::Find<JoinerIidTlv>(aMessage, joinerIid));
|
||||
SuccessOrExit(error = Tlv::Find<JoinerRouterLocatorTlv>(aMessage, joinerRloc));
|
||||
|
||||
SuccessOrExit(
|
||||
error = Tlv::FindTlvValueStartEndOffsets(aMessage, Tlv::kJoinerDtlsEncapsulation, startOffset, endOffset));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kJoinerDtlsEncapsulation, offsetRange));
|
||||
|
||||
if (!Get<Tmf::SecureAgent>().IsConnectionActive())
|
||||
{
|
||||
@@ -951,8 +949,8 @@ template <> void Commissioner::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, c
|
||||
|
||||
LogInfo("Received %s (%s, 0x%04x)", UriToString<kUriRelayRx>(), mJoinerIid.ToString().AsCString(), mJoinerRloc);
|
||||
|
||||
aMessage.SetOffset(startOffset);
|
||||
SuccessOrExit(error = aMessage.SetLength(endOffset));
|
||||
aMessage.SetOffset(offsetRange.GetOffset());
|
||||
SuccessOrExit(error = aMessage.SetLength(offsetRange.GetEndOffset()));
|
||||
|
||||
joinerMessageInfo.SetPeerAddr(Get<Mle::MleRouter>().GetMeshLocalEid());
|
||||
joinerMessageInfo.GetPeerAddr().SetIid(mJoinerIid);
|
||||
|
||||
@@ -337,14 +337,14 @@ void Dataset::SetFrom(const Info &aDatasetInfo)
|
||||
// `mUpdateTime` is already set by `WriteTlvsFrom()`.
|
||||
}
|
||||
|
||||
Error Dataset::SetFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
|
||||
Error Dataset::SetFrom(const Message &aMessage, const OffsetRange &aOffsetRange)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(aLength <= kMaxLength, error = kErrorInvalidArgs);
|
||||
VerifyOrExit(aOffsetRange.GetLength() <= kMaxLength, error = kErrorInvalidArgs);
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, mTlvs, aLength));
|
||||
mLength = static_cast<uint8_t>(aLength);
|
||||
SuccessOrExit(error = aMessage.Read(aOffsetRange, mTlvs, aOffsetRange.GetLength()));
|
||||
mLength = static_cast<uint8_t>(aOffsetRange.GetLength());
|
||||
|
||||
mUpdateTime = TimerMilli::GetNow();
|
||||
|
||||
|
||||
@@ -633,16 +633,15 @@ public:
|
||||
/**
|
||||
* Sets the Dataset by reading the TLVs bytes from given message.
|
||||
*
|
||||
* @param[in] aMessage The message to read from.
|
||||
* @param[in] aOffset The offset in @p aMessage to start reading the Dataset TLVs.
|
||||
* @param[in] aLength The dataset length in bytes.
|
||||
* @param[in] aMessage The message to read from.
|
||||
* @param[in] aOffsetRange The offset range in @p aMessage to read the Dataset TLVs.
|
||||
*
|
||||
* @retval kErrorNone Successfully set the Dataset.
|
||||
* @retval kInvalidArgs The @p aLength is longer than `kMaxLength`.
|
||||
* @retval kInvalidArgs The given offset range length is longer than `kMaxLength`.
|
||||
* @retval kErrorParse Could not read or parse the dataset from @p aMessage.
|
||||
*
|
||||
*/
|
||||
Error SetFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
|
||||
Error SetFrom(const Message &aMessage, const OffsetRange &aOffsetRange);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the start of Dataset TLVs sequence.
|
||||
|
||||
@@ -532,17 +532,17 @@ exit:
|
||||
|
||||
void DatasetManager::HandleGet(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
|
||||
{
|
||||
TlvList tlvList;
|
||||
uint8_t tlvType;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
TlvList tlvList;
|
||||
uint8_t tlvType;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
SuccessOrExit(Tlv::FindTlvValueOffset(aMessage, Tlv::kGet, offset, length));
|
||||
SuccessOrExit(Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kGet, offsetRange));
|
||||
|
||||
for (; length > 0; length--, offset++)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
IgnoreError(aMessage.Read(offset, tlvType));
|
||||
IgnoreError(aMessage.Read(offsetRange, tlvType));
|
||||
tlvList.Add(tlvType);
|
||||
offsetRange.AdvanceOffset(sizeof(uint8_t));
|
||||
}
|
||||
|
||||
// MGMT_PENDING_GET.rsp must include Delay Timer TLV (Thread 1.1.1
|
||||
|
||||
@@ -71,6 +71,7 @@ Error DatasetManager::ProcessSetOrReplaceRequest(MgmtCommand aCommand,
|
||||
{
|
||||
Error error = kErrorParse;
|
||||
Dataset dataset;
|
||||
OffsetRange offsetRange;
|
||||
Timestamp activeTimestamp;
|
||||
ChannelTlvValue channelValue;
|
||||
uint16_t sessionId;
|
||||
@@ -81,7 +82,8 @@ Error DatasetManager::ProcessSetOrReplaceRequest(MgmtCommand aCommand,
|
||||
|
||||
aInfo.Clear();
|
||||
|
||||
SuccessOrExit(dataset.SetFrom(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset()));
|
||||
offsetRange.InitFromMessageOffsetToEnd(aMessage);
|
||||
SuccessOrExit(dataset.SetFrom(aMessage, offsetRange));
|
||||
SuccessOrExit(dataset.ValidateTlvs());
|
||||
|
||||
// Verify that the request includes timestamps that are
|
||||
|
||||
@@ -161,14 +161,16 @@ void DatasetUpdater::HandleNotifierEvents(Events aEvents)
|
||||
|
||||
void DatasetUpdater::HandleDatasetChanged(Dataset::Type aType)
|
||||
{
|
||||
Dataset requestedDataset;
|
||||
Dataset newDataset;
|
||||
Timestamp newTimestamp;
|
||||
Timestamp requestedTimestamp;
|
||||
Dataset requestedDataset;
|
||||
Dataset newDataset;
|
||||
Timestamp newTimestamp;
|
||||
Timestamp requestedTimestamp;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
VerifyOrExit(IsUpdateOngoing());
|
||||
|
||||
SuccessOrExit(requestedDataset.SetFrom(*mDataset, /* aOffset */ 0, mDataset->GetLength()));
|
||||
offsetRange.InitFromMessageFullLength(*mDataset);
|
||||
SuccessOrExit(requestedDataset.SetFrom(*mDataset, offsetRange));
|
||||
|
||||
if (aType == Dataset::kActive)
|
||||
{
|
||||
|
||||
@@ -133,6 +133,7 @@ void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a
|
||||
Tmf::MessageInfo messageInfo(GetInstance());
|
||||
ExtendedTlv tlv;
|
||||
uint16_t borderAgentRloc;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
LogInfo("JoinerRouter::HandleUdpReceive");
|
||||
|
||||
@@ -145,10 +146,12 @@ void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a
|
||||
SuccessOrExit(error = Tlv::Append<JoinerIidTlv>(*message, aMessageInfo.GetPeerAddr().GetIid()));
|
||||
SuccessOrExit(error = Tlv::Append<JoinerRouterLocatorTlv>(*message, Get<Mle::MleRouter>().GetRloc16()));
|
||||
|
||||
offsetRange.InitFromMessageOffsetToEnd(aMessage);
|
||||
|
||||
tlv.SetType(Tlv::kJoinerDtlsEncapsulation);
|
||||
tlv.SetLength(aMessage.GetLength() - aMessage.GetOffset());
|
||||
tlv.SetLength(offsetRange.GetLength());
|
||||
SuccessOrExit(error = message->Append(tlv));
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, aMessage.GetOffset(), tlv.GetLength()));
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
|
||||
|
||||
messageInfo.SetSockAddrToRlocPeerAddrTo(borderAgentRloc);
|
||||
|
||||
@@ -168,8 +171,7 @@ template <> void JoinerRouter::HandleTmf<kUriRelayTx>(Coap::Message &aMessage, c
|
||||
uint16_t joinerPort;
|
||||
Ip6::InterfaceIdentifier joinerIid;
|
||||
Kek kek;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
OffsetRange offsetRange;
|
||||
Message *message = nullptr;
|
||||
Message::Settings settings(Message::kNoLinkSecurity, Message::kPriorityNet);
|
||||
Ip6::MessageInfo messageInfo;
|
||||
@@ -181,11 +183,11 @@ template <> void JoinerRouter::HandleTmf<kUriRelayTx>(Coap::Message &aMessage, c
|
||||
SuccessOrExit(error = Tlv::Find<JoinerUdpPortTlv>(aMessage, joinerPort));
|
||||
SuccessOrExit(error = Tlv::Find<JoinerIidTlv>(aMessage, joinerIid));
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Tlv::kJoinerDtlsEncapsulation, offset, length));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kJoinerDtlsEncapsulation, offsetRange));
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0, settings)) != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offset, length));
|
||||
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
|
||||
|
||||
messageInfo.GetPeerAddr().SetToLinkLocalAddress(joinerIid);
|
||||
messageInfo.SetPeerPort(joinerPort);
|
||||
|
||||
@@ -146,12 +146,15 @@ Error ChannelMaskTlv::FindIn(const Message &aMessage, uint32_t &aChannelMask)
|
||||
{
|
||||
Error error;
|
||||
EntriesData entriesData;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
entriesData.Clear();
|
||||
entriesData.mMessage = &aMessage;
|
||||
|
||||
SuccessOrExit(error = FindTlvValueOffset(aMessage, Tlv::kChannelMask, entriesData.mOffset, entriesData.mLength));
|
||||
error = entriesData.Parse(aChannelMask);
|
||||
SuccessOrExit(error = FindTlvValueOffsetRange(aMessage, Tlv::kChannelMask, offsetRange));
|
||||
entriesData.mOffset = offsetRange.GetOffset();
|
||||
entriesData.mLength = offsetRange.GetLength();
|
||||
error = entriesData.Parse(aChannelMask);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
@@ -462,10 +462,12 @@ exit:
|
||||
|
||||
Error TcatAgent::HandleSetActiveOperationalDataset(const Message &aIncommingMessage, uint16_t aOffset, uint16_t aLength)
|
||||
{
|
||||
Dataset dataset;
|
||||
Error error;
|
||||
Dataset dataset;
|
||||
OffsetRange offsetRange;
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = dataset.SetFrom(aIncommingMessage, aOffset, aLength));
|
||||
offsetRange.Init(aOffset, aLength);
|
||||
SuccessOrExit(error = dataset.SetFrom(aIncommingMessage, offsetRange));
|
||||
SuccessOrExit(error = dataset.ValidateTlvs());
|
||||
|
||||
if (!CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mApplicationFlags,
|
||||
|
||||
@@ -312,8 +312,7 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
|
||||
MeshCoP::Tlv meshcopTlv;
|
||||
MeshCoP::DiscoveryResponseTlv discoveryResponse;
|
||||
ScanResult result;
|
||||
uint16_t offset;
|
||||
uint16_t end;
|
||||
OffsetRange offsetRange;
|
||||
bool didCheckSteeringData = false;
|
||||
|
||||
Mle::Log(Mle::kMessageReceive, Mle::kTypeDiscoveryResponse, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
@@ -321,7 +320,7 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
|
||||
VerifyOrExit(mState == kStateScanning, error = kErrorDrop);
|
||||
|
||||
// Find MLE Discovery TLV
|
||||
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aRxInfo.mMessage, Tlv::kDiscovery, offset, end));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRxInfo.mMessage, Tlv::kDiscovery, offsetRange));
|
||||
|
||||
ClearAllBytes(result);
|
||||
result.mDiscover = true;
|
||||
@@ -333,35 +332,35 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
|
||||
aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(AsCoreType(&result.mExtAddress));
|
||||
|
||||
// Process MeshCoP TLVs
|
||||
while (offset < end)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, meshcopTlv));
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, meshcopTlv));
|
||||
|
||||
if (meshcopTlv.IsExtended())
|
||||
{
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aRxInfo.mMessage, offset));
|
||||
VerifyOrExit(offset <= end, error = kErrorParse);
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aRxInfo.mMessage, offsetRange));
|
||||
continue;
|
||||
}
|
||||
|
||||
VerifyOrExit(meshcopTlv.GetSize() + offset <= aRxInfo.mMessage.GetLength(), error = kErrorParse);
|
||||
VerifyOrExit(offsetRange.Contains(meshcopTlv.GetSize()), error = kErrorParse);
|
||||
|
||||
switch (meshcopTlv.GetType())
|
||||
{
|
||||
case MeshCoP::Tlv::kDiscoveryResponse:
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, discoveryResponse));
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, discoveryResponse));
|
||||
VerifyOrExit(discoveryResponse.IsValid(), error = kErrorParse);
|
||||
result.mVersion = discoveryResponse.GetVersion();
|
||||
result.mIsNative = discoveryResponse.IsNativeCommissioner();
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kExtendedPanId:
|
||||
SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offset,
|
||||
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, offset, result.mNetworkName.m8));
|
||||
SuccessOrExit(error = Tlv::Read<MeshCoP::NetworkNameTlv>(aRxInfo.mMessage, offsetRange.GetOffset(),
|
||||
result.mNetworkName.m8));
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kSteeringData:
|
||||
@@ -377,7 +376,8 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
|
||||
|
||||
steeringData.Init(dataLength);
|
||||
|
||||
SuccessOrExit(error = Tlv::ReadTlvValue(aRxInfo.mMessage, offset, steeringData.GetData(), dataLength));
|
||||
SuccessOrExit(error = Tlv::ReadTlvValue(aRxInfo.mMessage, offsetRange.GetOffset(),
|
||||
steeringData.GetData(), dataLength));
|
||||
|
||||
if (mEnableFiltering)
|
||||
{
|
||||
@@ -389,15 +389,15 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kJoinerUdpPort:
|
||||
SuccessOrExit(error =
|
||||
Tlv::Read<MeshCoP::JoinerUdpPortTlv>(aRxInfo.mMessage, offset, result.mJoinerUdpPort));
|
||||
SuccessOrExit(error = Tlv::Read<MeshCoP::JoinerUdpPortTlv>(aRxInfo.mMessage, offsetRange.GetOffset(),
|
||||
result.mJoinerUdpPort));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
|
||||
offsetRange.AdvanceOffset(meshcopTlv.GetSize());
|
||||
}
|
||||
|
||||
VerifyOrExit(!mEnableFiltering || didCheckSteeringData);
|
||||
|
||||
@@ -123,11 +123,9 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t aLength, const Ip6::Address &aAddress)
|
||||
void Initiator::HandleReport(const Message &aMessage, OffsetRange &aOffsetRange, const Ip6::Address &aAddress)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t offset = aOffset;
|
||||
uint16_t endOffset = aOffset + aLength;
|
||||
bool hasStatus = false;
|
||||
bool hasReport = false;
|
||||
Tlv tlv;
|
||||
@@ -142,18 +140,17 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
|
||||
|
||||
values.Clear();
|
||||
|
||||
while (offset < endOffset)
|
||||
while (!aOffsetRange.IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aMessage.Read(offset, tlv));
|
||||
SuccessOrExit(error = aMessage.Read(aOffsetRange, tlv));
|
||||
|
||||
if (tlv.IsExtended())
|
||||
{
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offset));
|
||||
VerifyOrExit(offset <= endOffset, error = kErrorParse);
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, aOffsetRange));
|
||||
continue;
|
||||
}
|
||||
|
||||
VerifyOrExit(tlv.GetSize() + offset <= endOffset, error = kErrorParse);
|
||||
VerifyOrExit(aOffsetRange.Contains(tlv.GetSize()), error = kErrorParse);
|
||||
|
||||
// The report must contain either:
|
||||
// - One or more Report Sub-TLVs (in case of success), or
|
||||
@@ -163,7 +160,7 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
|
||||
{
|
||||
case StatusSubTlv::kType:
|
||||
VerifyOrExit(!hasStatus && !hasReport, error = kErrorDrop);
|
||||
SuccessOrExit(error = Tlv::Read<StatusSubTlv>(aMessage, offset, status));
|
||||
SuccessOrExit(error = Tlv::Read<StatusSubTlv>(aMessage, aOffsetRange.GetOffset(), status));
|
||||
hasStatus = true;
|
||||
break;
|
||||
|
||||
@@ -171,7 +168,7 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
|
||||
VerifyOrExit(!hasStatus, error = kErrorDrop);
|
||||
|
||||
// Read the report sub-TLV assuming minimum length
|
||||
SuccessOrExit(error = aMessage.Read(offset, &reportTlv, sizeof(Tlv) + ReportSubTlv::kMinLength));
|
||||
SuccessOrExit(error = aMessage.Read(aOffsetRange, &reportTlv, sizeof(Tlv) + ReportSubTlv::kMinLength));
|
||||
VerifyOrExit(reportTlv.IsValid(), error = kErrorParse);
|
||||
hasReport = true;
|
||||
|
||||
@@ -187,7 +184,7 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
|
||||
{
|
||||
// If Type ID indicates metric value has 4 bytes length, we
|
||||
// read the full `reportTlv`.
|
||||
SuccessOrExit(error = aMessage.Read(offset, reportTlv));
|
||||
SuccessOrExit(error = aMessage.Read(aOffsetRange.GetOffset(), reportTlv));
|
||||
}
|
||||
|
||||
switch (typeId)
|
||||
@@ -220,7 +217,7 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
|
||||
break;
|
||||
}
|
||||
|
||||
offset += sizeof(Tlv) + tlv.GetLength();
|
||||
aOffsetRange.AdvanceOffset(tlv.GetSize());
|
||||
}
|
||||
|
||||
VerifyOrExit(hasStatus || hasReport);
|
||||
@@ -310,37 +307,34 @@ exit:
|
||||
|
||||
Error Initiator::HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t offset;
|
||||
uint16_t endOffset;
|
||||
uint8_t status;
|
||||
bool hasStatus = false;
|
||||
Error error = kErrorNone;
|
||||
OffsetRange offsetRange;
|
||||
uint8_t status;
|
||||
bool hasStatus = false;
|
||||
|
||||
VerifyOrExit(mMgmtResponseCallback.IsSet());
|
||||
|
||||
SuccessOrExit(
|
||||
error = Tlv::FindTlvValueStartEndOffsets(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, endOffset));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offsetRange));
|
||||
|
||||
while (offset < endOffset)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
Tlv tlv;
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(offset, tlv));
|
||||
SuccessOrExit(error = aMessage.Read(offsetRange, tlv));
|
||||
|
||||
if (tlv.IsExtended())
|
||||
{
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offset));
|
||||
VerifyOrExit(offset <= endOffset, error = kErrorParse);
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offsetRange));
|
||||
continue;
|
||||
}
|
||||
|
||||
VerifyOrExit(tlv.GetSize() + offset <= endOffset, error = kErrorParse);
|
||||
VerifyOrExit(offsetRange.Contains(tlv.GetSize()), error = kErrorParse);
|
||||
|
||||
switch (tlv.GetType())
|
||||
{
|
||||
case StatusSubTlv::kType:
|
||||
VerifyOrExit(!hasStatus, error = kErrorParse);
|
||||
SuccessOrExit(error = Tlv::Read<StatusSubTlv>(aMessage, offset, status));
|
||||
SuccessOrExit(error = Tlv::Read<StatusSubTlv>(aMessage, offsetRange.GetOffset(), status));
|
||||
hasStatus = true;
|
||||
break;
|
||||
|
||||
@@ -348,7 +342,7 @@ Error Initiator::HandleManagementResponse(const Message &aMessage, const Ip6::Ad
|
||||
break;
|
||||
}
|
||||
|
||||
offset += sizeof(Tlv) + tlv.GetLength();
|
||||
offsetRange.AdvanceOffset(tlv.GetSize());
|
||||
}
|
||||
|
||||
VerifyOrExit(hasStatus, error = kErrorParse);
|
||||
@@ -440,7 +434,7 @@ Error Subject::AppendReport(Message &aMessage, const Message &aRequestMessage, N
|
||||
bool hasQueryId = false;
|
||||
uint16_t length;
|
||||
uint16_t offset;
|
||||
uint16_t endOffset;
|
||||
OffsetRange offsetRange;
|
||||
MetricsValues values;
|
||||
|
||||
values.Clear();
|
||||
@@ -449,40 +443,43 @@ Error Subject::AppendReport(Message &aMessage, const Message &aRequestMessage, N
|
||||
// Parse MLE Link Metrics Query TLV and its sub-TLVs from
|
||||
// `aRequestMessage`.
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aRequestMessage, Mle::Tlv::Type::kLinkMetricsQuery, offset,
|
||||
endOffset));
|
||||
SuccessOrExit(error =
|
||||
Tlv::FindTlvValueOffsetRange(aRequestMessage, Mle::Tlv::Type::kLinkMetricsQuery, offsetRange));
|
||||
|
||||
while (offset < endOffset)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aRequestMessage.Read(offset, tlv));
|
||||
OffsetRange tlvOffsetRange;
|
||||
|
||||
SuccessOrExit(error = aRequestMessage.Read(offsetRange, tlv));
|
||||
|
||||
if (tlv.IsExtended())
|
||||
{
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offset));
|
||||
VerifyOrExit(offset <= endOffset, error = kErrorParse);
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offsetRange));
|
||||
continue;
|
||||
}
|
||||
|
||||
VerifyOrExit(tlv.GetSize() + offset <= endOffset, error = kErrorParse);
|
||||
VerifyOrExit(offsetRange.Contains(tlv.GetSize()), error = kErrorParse);
|
||||
|
||||
tlvOffsetRange = offsetRange;
|
||||
tlvOffsetRange.ShrinkLength(tlv.GetSize());
|
||||
|
||||
switch (tlv.GetType())
|
||||
{
|
||||
case SubTlv::kQueryId:
|
||||
SuccessOrExit(error = Tlv::Read<QueryIdSubTlv>(aRequestMessage, offset, queryId));
|
||||
SuccessOrExit(error = Tlv::Read<QueryIdSubTlv>(aRequestMessage, tlvOffsetRange.GetOffset(), queryId));
|
||||
hasQueryId = true;
|
||||
break;
|
||||
|
||||
case SubTlv::kQueryOptions:
|
||||
SuccessOrExit(error = ReadTypeIdsFromMessage(aRequestMessage, offset + sizeof(tlv),
|
||||
static_cast<uint16_t>(offset + tlv.GetSize()),
|
||||
values.GetMetrics()));
|
||||
tlvOffsetRange.AdvanceOffset(sizeof(tlv));
|
||||
SuccessOrExit(error = ReadTypeIdsFromMessage(aRequestMessage, tlvOffsetRange, values.GetMetrics()));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
offset += static_cast<uint16_t>(tlv.GetSize());
|
||||
offsetRange.AdvanceOffset(tlv.GetSize());
|
||||
}
|
||||
|
||||
VerifyOrExit(hasQueryId, error = kErrorParse);
|
||||
@@ -539,31 +536,39 @@ exit:
|
||||
Error Subject::HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t offset;
|
||||
uint16_t endOffset;
|
||||
uint16_t tlvEndOffset;
|
||||
OffsetRange offsetRange;
|
||||
FwdProbingRegSubTlv fwdProbingSubTlv;
|
||||
EnhAckConfigSubTlv enhAckConfigSubTlv;
|
||||
Metrics metrics;
|
||||
|
||||
SuccessOrExit(
|
||||
error = Tlv::FindTlvValueStartEndOffsets(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, endOffset));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offsetRange));
|
||||
|
||||
// Set sub-TLV lengths to zero to indicate that we have
|
||||
// not yet seen them in the message.
|
||||
fwdProbingSubTlv.SetLength(0);
|
||||
enhAckConfigSubTlv.SetLength(0);
|
||||
|
||||
for (; offset < endOffset; offset = tlvEndOffset)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
Tlv tlv;
|
||||
uint16_t minTlvSize;
|
||||
Tlv *subTlv;
|
||||
Tlv tlv;
|
||||
uint16_t minTlvSize;
|
||||
Tlv *subTlv;
|
||||
OffsetRange tlvOffsetRange;
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(offset, tlv));
|
||||
SuccessOrExit(error = aMessage.Read(offsetRange, tlv));
|
||||
|
||||
VerifyOrExit(offset + tlv.GetSize() <= endOffset, error = kErrorParse);
|
||||
tlvEndOffset = static_cast<uint16_t>(offset + tlv.GetSize());
|
||||
if (tlv.IsExtended())
|
||||
{
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offsetRange));
|
||||
continue;
|
||||
}
|
||||
|
||||
VerifyOrExit(offsetRange.Contains(tlv.GetSize()), error = kErrorParse);
|
||||
|
||||
tlvOffsetRange = offsetRange;
|
||||
tlvOffsetRange.ShrinkLength(tlv.GetSize());
|
||||
|
||||
offsetRange.AdvanceOffset(tlv.GetSize());
|
||||
|
||||
switch (tlv.GetType())
|
||||
{
|
||||
@@ -588,8 +593,10 @@ Error Subject::HandleManagementRequest(const Message &aMessage, Neighbor &aNeigh
|
||||
VerifyOrExit(tlv.GetSize() >= minTlvSize, error = kErrorParse);
|
||||
|
||||
// Read `subTlv` with its `minTlvSize`, followed by the Type IDs.
|
||||
SuccessOrExit(error = aMessage.Read(offset, subTlv, minTlvSize));
|
||||
SuccessOrExit(error = ReadTypeIdsFromMessage(aMessage, offset + minTlvSize, tlvEndOffset, metrics));
|
||||
SuccessOrExit(error = aMessage.Read(tlvOffsetRange.GetOffset(), subTlv, minTlvSize));
|
||||
|
||||
tlvOffsetRange.AdvanceOffset(minTlvSize);
|
||||
SuccessOrExit(error = ReadTypeIdsFromMessage(aMessage, tlvOffsetRange, metrics));
|
||||
}
|
||||
|
||||
if (fwdProbingSubTlv.GetLength() != 0)
|
||||
@@ -609,13 +616,11 @@ exit:
|
||||
|
||||
Error Subject::HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
Error error = kErrorNone;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkProbe, offset, length));
|
||||
VerifyOrExit(length >= sizeof(aSeriesId), error = kErrorParse);
|
||||
error = aMessage.Read(offset, aSeriesId);
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Mle::Tlv::Type::kLinkProbe, offsetRange));
|
||||
error = aMessage.Read(offsetRange, aSeriesId);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -662,20 +667,17 @@ exit:
|
||||
|
||||
void Subject::Free(SeriesInfo &aSeriesInfo) { mSeriesInfoPool.Free(aSeriesInfo); }
|
||||
|
||||
Error Subject::ReadTypeIdsFromMessage(const Message &aMessage,
|
||||
uint16_t aStartOffset,
|
||||
uint16_t aEndOffset,
|
||||
Metrics &aMetrics)
|
||||
Error Subject::ReadTypeIdsFromMessage(const Message &aMessage, OffsetRange &aOffsetRange, Metrics &aMetrics)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
aMetrics.Clear();
|
||||
|
||||
for (uint16_t offset = aStartOffset; offset < aEndOffset; offset++)
|
||||
while (!aOffsetRange.IsEmpty())
|
||||
{
|
||||
uint8_t typeId;
|
||||
|
||||
SuccessOrExit(aMessage.Read(offset, typeId));
|
||||
SuccessOrExit(aMessage.Read(aOffsetRange, typeId));
|
||||
|
||||
switch (typeId)
|
||||
{
|
||||
@@ -702,7 +704,7 @@ Error Subject::ReadTypeIdsFromMessage(const Message &aMessage,
|
||||
default:
|
||||
if (TypeId::IsExtended(typeId))
|
||||
{
|
||||
offset += sizeof(uint8_t); // Skip the additional second byte.
|
||||
aOffsetRange.AdvanceOffset(sizeof(uint8_t)); // Skip the additional second byte.
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -710,6 +712,8 @@ Error Subject::ReadTypeIdsFromMessage(const Message &aMessage,
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
aOffsetRange.AdvanceOffset(sizeof(uint8_t));
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
@@ -148,12 +148,11 @@ public:
|
||||
* Handles the received Link Metrics report contained in @p aMessage.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
* @param[in] aOffset The offset in bytes where the metrics report sub-TLVs start.
|
||||
* @param[in] aLength The length of the metrics report sub-TLVs in bytes.
|
||||
* @param[in] aOffsetRange The offset range in @p aMessage where the metrics report sub-TLVs are present.
|
||||
* @param[in] aAddress A reference to the source address of the message.
|
||||
*
|
||||
*/
|
||||
void HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t aLength, const Ip6::Address &aAddress);
|
||||
void HandleReport(const Message &aMessage, OffsetRange &aOffsetRange, const Ip6::Address &aAddress);
|
||||
|
||||
/**
|
||||
* Sends an MLE Link Metrics Management Request to configure/clear a Forward Tracking Series.
|
||||
@@ -342,10 +341,7 @@ private:
|
||||
static constexpr uint16_t kMaxSeriesSupported = OPENTHREAD_CONFIG_MLE_LINK_METRICS_SERIES_MTD;
|
||||
#endif
|
||||
|
||||
static Error ReadTypeIdsFromMessage(const Message &aMessage,
|
||||
uint16_t aStartOffset,
|
||||
uint16_t aEndOffset,
|
||||
Metrics &aMetrics);
|
||||
static Error ReadTypeIdsFromMessage(const Message &aMessage, OffsetRange &aOffsetRange, Metrics &aMetrics);
|
||||
static Error AppendReportSubTlvToMessage(Message &aMessage, const MetricsValues &aValues);
|
||||
|
||||
Status ConfigureForwardTrackingSeries(uint8_t aSeriesId,
|
||||
|
||||
+22
-31
@@ -2842,12 +2842,11 @@ void Mle::HandleDataResponse(RxInfo &aRxInfo)
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
|
||||
{
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
if (Tlv::FindTlvValueOffset(aRxInfo.mMessage, Tlv::kLinkMetricsReport, offset, length) == kErrorNone)
|
||||
if (Tlv::FindTlvValueOffsetRange(aRxInfo.mMessage, Tlv::kLinkMetricsReport, offsetRange) == kErrorNone)
|
||||
{
|
||||
Get<LinkMetrics::Initiator>().HandleReport(aRxInfo.mMessage, offset, length,
|
||||
Get<LinkMetrics::Initiator>().HandleReport(aRxInfo.mMessage, offsetRange,
|
||||
aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
}
|
||||
}
|
||||
@@ -4948,10 +4947,9 @@ exit:
|
||||
|
||||
bool Mle::RxMessage::ContainsTlv(Tlv::Type aTlvType) const
|
||||
{
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
return Tlv::FindTlvValueOffset(*this, aTlvType, offset, length) == kErrorNone;
|
||||
return Tlv::FindTlvValueOffsetRange(*this, aTlvType, offsetRange) == kErrorNone;
|
||||
}
|
||||
|
||||
Error Mle::RxMessage::ReadModeTlv(DeviceMode &aMode) const
|
||||
@@ -4979,12 +4977,11 @@ exit:
|
||||
|
||||
Error Mle::RxMessage::ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const
|
||||
{
|
||||
Error error;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
Error error;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, aTlvType, offset, length));
|
||||
error = aRxChallenge.ReadFrom(*this, offset, length);
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(*this, aTlvType, offsetRange));
|
||||
error = aRxChallenge.ReadFrom(*this, offsetRange);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -5049,15 +5046,14 @@ exit:
|
||||
|
||||
Error Mle::RxMessage::ReadAndSetNetworkDataTlv(const LeaderData &aLeaderData) const
|
||||
{
|
||||
Error error;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
Error error;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, Tlv::kNetworkData, offset, length));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(*this, Tlv::kNetworkData, offsetRange));
|
||||
|
||||
error = Get<NetworkData::Leader>().SetNetworkData(aLeaderData.GetDataVersion(NetworkData::kFullSet),
|
||||
aLeaderData.GetDataVersion(NetworkData::kStableSubset),
|
||||
Get<Mle>().GetNetworkDataType(), *this, offset, length);
|
||||
Get<Mle>().GetNetworkDataType(), *this, offsetRange);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -5078,12 +5074,11 @@ Error Mle::RxMessage::ReadAndSaveDataset(MeshCoP::Dataset::Type aDatasetType,
|
||||
Error error = kErrorNone;
|
||||
Tlv::Type tlvType = (aDatasetType == MeshCoP::Dataset::kActive) ? Tlv::kActiveDataset : Tlv::kPendingDataset;
|
||||
MeshCoP::Dataset dataset;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, tlvType, offset, length));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(*this, tlvType, offsetRange));
|
||||
|
||||
SuccessOrExit(error = dataset.SetFrom(*this, offset, length));
|
||||
SuccessOrExit(error = dataset.SetFrom(*this, offsetRange));
|
||||
SuccessOrExit(error = dataset.ValidateTlvs());
|
||||
SuccessOrExit(error = dataset.WriteTimestamp(aDatasetType, aTimestamp));
|
||||
|
||||
@@ -5103,19 +5098,15 @@ exit:
|
||||
|
||||
Error Mle::RxMessage::ReadTlvRequestTlv(TlvList &aTlvList) const
|
||||
{
|
||||
Error error;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
Error error;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, Tlv::kTlvRequest, offset, length));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(*this, Tlv::kTlvRequest, offsetRange));
|
||||
|
||||
if (length > aTlvList.GetMaxSize())
|
||||
{
|
||||
length = aTlvList.GetMaxSize();
|
||||
}
|
||||
offsetRange.ShrinkLength(aTlvList.GetMaxSize());
|
||||
|
||||
ReadBytes(offset, aTlvList.GetArrayBuffer(), length);
|
||||
aTlvList.SetLength(static_cast<uint8_t>(length));
|
||||
ReadBytes(offsetRange, aTlvList.GetArrayBuffer());
|
||||
aTlvList.SetLength(static_cast<uint8_t>(offsetRange.GetLength()));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
@@ -1761,11 +1761,10 @@ exit:
|
||||
|
||||
Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
|
||||
{
|
||||
Error error;
|
||||
uint16_t offset;
|
||||
uint16_t endOffset;
|
||||
uint8_t count = 0;
|
||||
uint8_t storedCount = 0;
|
||||
Error error;
|
||||
OffsetRange offsetRange;
|
||||
uint8_t count = 0;
|
||||
uint8_t storedCount = 0;
|
||||
#if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
|
||||
Ip6::Address oldDua;
|
||||
#endif
|
||||
@@ -1775,8 +1774,7 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
|
||||
|
||||
OT_UNUSED_VARIABLE(storedCount);
|
||||
|
||||
SuccessOrExit(error =
|
||||
Tlv::FindTlvValueStartEndOffsets(aRxInfo.mMessage, Tlv::kAddressRegistration, offset, endOffset));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRxInfo.mMessage, Tlv::kAddressRegistration, offsetRange));
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
|
||||
if (aChild.GetDomainUnicastAddress(oldDua) != kErrorNone)
|
||||
@@ -1807,14 +1805,14 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
|
||||
|
||||
aChild.ClearIp6Addresses();
|
||||
|
||||
while (offset < endOffset)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
uint8_t controlByte;
|
||||
Ip6::Address address;
|
||||
|
||||
// Read out the control byte (first byte in entry)
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, controlByte));
|
||||
offset++;
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, controlByte));
|
||||
offsetRange.AdvanceOffset(sizeof(uint8_t));
|
||||
count++;
|
||||
|
||||
address.Clear();
|
||||
@@ -1828,9 +1826,8 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
|
||||
uint8_t contextId = AddressRegistrationTlv::GetContextId(controlByte);
|
||||
Lowpan::Context context;
|
||||
|
||||
VerifyOrExit(offset + sizeof(Ip6::InterfaceIdentifier) <= endOffset, error = kErrorParse);
|
||||
IgnoreError(aRxInfo.mMessage.Read(offset, address.GetIid()));
|
||||
offset += sizeof(Ip6::InterfaceIdentifier);
|
||||
IgnoreError(aRxInfo.mMessage.Read(offsetRange, address.GetIid()));
|
||||
offsetRange.AdvanceOffset(sizeof(Ip6::InterfaceIdentifier));
|
||||
|
||||
if (Get<NetworkData::Leader>().GetContext(contextId, context) != kErrorNone)
|
||||
{
|
||||
@@ -1845,9 +1842,8 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
|
||||
{
|
||||
// Uncompressed entry contains the full IPv6 address.
|
||||
|
||||
VerifyOrExit(offset + sizeof(Ip6::Address) <= endOffset, error = kErrorParse);
|
||||
IgnoreError(aRxInfo.mMessage.Read(offset, address));
|
||||
offset += sizeof(Ip6::Address);
|
||||
IgnoreError(aRxInfo.mMessage.Read(offsetRange, address));
|
||||
offsetRange.AdvanceOffset(sizeof(Ip6::Address));
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
@@ -2624,8 +2620,7 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
|
||||
MeshCoP::Tlv meshcopTlv;
|
||||
MeshCoP::DiscoveryRequestTlv discoveryRequestTlv;
|
||||
MeshCoP::ExtendedPanId extPanId;
|
||||
uint16_t offset;
|
||||
uint16_t end;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
Log(kMessageReceive, kTypeDiscoveryRequest, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
|
||||
@@ -2633,31 +2628,31 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
|
||||
|
||||
VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aRxInfo.mMessage, Tlv::kDiscovery, offset, end));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRxInfo.mMessage, Tlv::kDiscovery, offsetRange));
|
||||
|
||||
while (offset < end)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, meshcopTlv));
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, meshcopTlv));
|
||||
|
||||
if (meshcopTlv.IsExtended())
|
||||
{
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aRxInfo.mMessage, offset));
|
||||
VerifyOrExit(offset <= end, error = kErrorParse);
|
||||
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aRxInfo.mMessage, offsetRange));
|
||||
continue;
|
||||
}
|
||||
|
||||
VerifyOrExit(meshcopTlv.GetSize() + offset <= aRxInfo.mMessage.GetLength(), error = kErrorParse);
|
||||
VerifyOrExit(offsetRange.Contains(meshcopTlv.GetSize()));
|
||||
|
||||
switch (meshcopTlv.GetType())
|
||||
{
|
||||
case MeshCoP::Tlv::kDiscoveryRequest:
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, discoveryRequestTlv));
|
||||
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, discoveryRequestTlv));
|
||||
VerifyOrExit(discoveryRequestTlv.IsValid(), error = kErrorParse);
|
||||
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kExtendedPanId:
|
||||
SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offset, extPanId));
|
||||
SuccessOrExit(
|
||||
error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offsetRange.GetOffset(), extPanId));
|
||||
VerifyOrExit(Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId() != extPanId, error = kErrorDrop);
|
||||
|
||||
break;
|
||||
@@ -2666,7 +2661,7 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
|
||||
break;
|
||||
}
|
||||
|
||||
offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
|
||||
offsetRange.AdvanceOffset(meshcopTlv.GetSize());
|
||||
}
|
||||
|
||||
if (discoveryRequestTlv.IsValid())
|
||||
|
||||
@@ -160,17 +160,19 @@ void TxChallenge::GenerateRandom(void) { IgnoreError(Random::Crypto::Fill(*this)
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// RxChallenge
|
||||
|
||||
Error RxChallenge::ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
|
||||
Error RxChallenge::ReadFrom(const Message &aMessage, const OffsetRange &aOffsetRange)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error = kErrorNone;
|
||||
OffsetRange offsetRange = aOffsetRange;
|
||||
|
||||
Clear();
|
||||
|
||||
aLength = Min<uint16_t>(aLength, kMaxSize);
|
||||
VerifyOrExit(kMinSize <= aLength, error = kErrorParse);
|
||||
offsetRange.ShrinkLength(kMaxSize);
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, mArray.GetArrayBuffer(), aLength));
|
||||
mArray.SetLength(static_cast<uint8_t>(aLength));
|
||||
VerifyOrExit(offsetRange.Contains(kMinSize), error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(offsetRange, mArray.GetArrayBuffer(), offsetRange.GetLength()));
|
||||
mArray.SetLength(static_cast<uint8_t>(offsetRange.GetLength()));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/equatable.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "common/offset_range.hpp"
|
||||
#include "common/string.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "meshcop/extended_panid.hpp"
|
||||
@@ -526,15 +527,14 @@ public:
|
||||
*
|
||||
* If the given @p aLength is longer than `kMaxSize`, only `kMaxSize` bytes will be read.
|
||||
*
|
||||
* @param[in] aMessage The message to read the challenge from.
|
||||
* @param[in] aOffset The offset in @p aMessage to read from.
|
||||
* @param[in] aLength Number of bytes to read.
|
||||
* @param[in] aMessage The message to read the challenge from.
|
||||
* @param[in] aOffsetRange The offset range in @p aMessage to read from.
|
||||
*
|
||||
* @retval kErrorNone Successfully read the challenge data from @p aMessage.
|
||||
* @retval kErrorParse Not enough bytes to read, or invalid @p aLength (smaller than `kMinSize`).
|
||||
* @retval kErrorParse Not enough bytes to read, or invalid length (smaller than `kMinSize`).
|
||||
*
|
||||
*/
|
||||
Error ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
|
||||
Error ReadFrom(const Message &aMessage, const OffsetRange &aOffsetRange);
|
||||
|
||||
/**
|
||||
* Compares the `RxChallenge` with a given `TxChallenge`.
|
||||
|
||||
@@ -482,8 +482,8 @@ Error MlrManager::ParseMlrResponse(Error aResult,
|
||||
uint8_t &aStatus,
|
||||
AddressArray &aFailedAddresses)
|
||||
{
|
||||
Error error;
|
||||
uint16_t addressesOffset, addressesLength;
|
||||
Error error;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
aStatus = ThreadStatusTlv::kMlrGeneralFailure;
|
||||
|
||||
@@ -492,15 +492,16 @@ Error MlrManager::ParseMlrResponse(Error aResult,
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(*aMessage, aStatus));
|
||||
|
||||
if (ThreadTlv::FindTlvValueOffset(*aMessage, Ip6AddressesTlv::kIp6Addresses, addressesOffset, addressesLength) ==
|
||||
kErrorNone)
|
||||
if (ThreadTlv::FindTlvValueOffsetRange(*aMessage, Ip6AddressesTlv::kIp6Addresses, offsetRange) == kErrorNone)
|
||||
{
|
||||
VerifyOrExit(addressesLength % sizeof(Ip6::Address) == 0, error = kErrorParse);
|
||||
VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses, error = kErrorParse);
|
||||
VerifyOrExit(offsetRange.GetLength() % sizeof(Ip6::Address) == 0, error = kErrorParse);
|
||||
VerifyOrExit(offsetRange.GetLength() / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses,
|
||||
error = kErrorParse);
|
||||
|
||||
for (uint16_t offset = 0; offset < addressesLength; offset += sizeof(Ip6::Address))
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
IgnoreError(aMessage->Read(addressesOffset + offset, *aFailedAddresses.PushBack()));
|
||||
IgnoreError(aMessage->Read(offsetRange, *aFailedAddresses.PushBack()));
|
||||
offsetRange.AdvanceOffset(sizeof(Ip6::Address));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -426,19 +426,19 @@ Error Leader::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) co
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Leader::SetNetworkData(uint8_t aVersion,
|
||||
uint8_t aStableVersion,
|
||||
Type aType,
|
||||
const Message &aMessage,
|
||||
uint16_t aOffset,
|
||||
uint16_t aLength)
|
||||
Error Leader::SetNetworkData(uint8_t aVersion,
|
||||
uint8_t aStableVersion,
|
||||
Type aType,
|
||||
const Message &aMessage,
|
||||
const OffsetRange &aOffsetRange)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error = kErrorNone;
|
||||
uint16_t length = aOffsetRange.GetLength();
|
||||
|
||||
VerifyOrExit(aLength <= kMaxSize, error = kErrorParse);
|
||||
SuccessOrExit(error = aMessage.Read(aOffset, GetBytes(), aLength));
|
||||
VerifyOrExit(length <= kMaxSize, error = kErrorParse);
|
||||
SuccessOrExit(error = aMessage.Read(aOffsetRange.GetOffset(), GetBytes(), length));
|
||||
|
||||
SetLength(static_cast<uint8_t>(aLength));
|
||||
SetLength(static_cast<uint8_t>(length));
|
||||
mVersion = aVersion;
|
||||
mStableVersion = aStableVersion;
|
||||
|
||||
|
||||
@@ -168,19 +168,17 @@ public:
|
||||
* @param[in] aStableVersion The Stable Version value.
|
||||
* @param[in] aType The Network Data type to set, the full set or stable subset.
|
||||
* @param[in] aMessage A reference to the message.
|
||||
* @param[in] aOffset The offset in @p aMessage pointing to start of Network Data.
|
||||
* @param[in] aLength The length of Network Data.
|
||||
* @param[in] aOffsetRange The offset range in @p aMessage to read from.
|
||||
*
|
||||
* @retval kErrorNone Successfully set the network data.
|
||||
* @retval kErrorParse Network Data in @p aMessage is not valid.
|
||||
*
|
||||
*/
|
||||
Error SetNetworkData(uint8_t aVersion,
|
||||
uint8_t aStableVersion,
|
||||
Type aType,
|
||||
const Message &aMessage,
|
||||
uint16_t aOffset,
|
||||
uint16_t aLength);
|
||||
Error SetNetworkData(uint8_t aVersion,
|
||||
uint8_t aStableVersion,
|
||||
Type aType,
|
||||
const Message &aMessage,
|
||||
const OffsetRange &aOffsetRange);
|
||||
|
||||
/**
|
||||
* Gets the Commissioning Dataset from Network Data.
|
||||
|
||||
@@ -206,25 +206,25 @@ exit:
|
||||
|
||||
template <> void Leader::HandleTmf<kUriCommissionerGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
uint16_t length;
|
||||
uint16_t offset;
|
||||
Coap::Message *response = nullptr;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
VerifyOrExit(Get<Mle::Mle>().IsLeader() && !mWaitingForNetDataSync);
|
||||
|
||||
response = Get<Tmf::Agent>().NewPriorityResponseMessage(aMessage);
|
||||
VerifyOrExit(response != nullptr);
|
||||
|
||||
if (Tlv::FindTlvValueOffset(aMessage, MeshCoP::Tlv::kGet, offset, length) == kErrorNone)
|
||||
if (Tlv::FindTlvValueOffsetRange(aMessage, MeshCoP::Tlv::kGet, offsetRange) == kErrorNone)
|
||||
{
|
||||
// Append the requested sub-TLV types given in Get TLV.
|
||||
|
||||
for (; length > 0; offset++, length--)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
uint8_t type;
|
||||
const MeshCoP::Tlv *subTlv;
|
||||
|
||||
IgnoreError(aMessage.Read(offset, type));
|
||||
IgnoreError(aMessage.Read(offsetRange, type));
|
||||
offsetRange.AdvanceOffset(sizeof(type));
|
||||
|
||||
subTlv = FindCommissioningDataSubTlv(type);
|
||||
|
||||
@@ -1334,12 +1334,14 @@ exit:
|
||||
|
||||
Error Leader::SetCommissioningData(const Message &aMessage)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t dataLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
Error error = kErrorNone;
|
||||
OffsetRange offsetRange;
|
||||
CommissioningDataTlv *dataTlv;
|
||||
|
||||
SuccessOrExit(error = UpdateCommissioningData(dataLength, dataTlv));
|
||||
aMessage.ReadBytes(aMessage.GetOffset(), dataTlv->GetValue(), dataLength);
|
||||
offsetRange.InitFromMessageOffsetToEnd(aMessage);
|
||||
|
||||
SuccessOrExit(error = UpdateCommissioningData(offsetRange.GetLength(), dataTlv));
|
||||
aMessage.ReadBytes(offsetRange, dataTlv->GetValue());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
@@ -239,17 +239,17 @@ Error Server::AppendMacCounters(Message &aMessage)
|
||||
|
||||
Error Server::AppendRequestedTlvs(const Message &aRequest, Message &aResponse)
|
||||
{
|
||||
Error error;
|
||||
uint16_t offset;
|
||||
uint16_t endOffset;
|
||||
Error error;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aRequest, Tlv::kTypeList, offset, endOffset));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRequest, Tlv::kTypeList, offsetRange));
|
||||
|
||||
for (; offset < endOffset; offset++)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
uint8_t tlvType;
|
||||
|
||||
SuccessOrExit(error = aRequest.Read(offset, tlvType));
|
||||
SuccessOrExit(error = aRequest.Read(offsetRange, tlvType));
|
||||
offsetRange.AdvanceOffset(sizeof(tlvType));
|
||||
SuccessOrExit(error = AppendDiagTlv(tlvType, aResponse));
|
||||
}
|
||||
|
||||
@@ -536,9 +536,7 @@ void Server::PrepareAndSendAnswers(const Ip6::Address &aDestination, const Messa
|
||||
Coap::Message *answer;
|
||||
Error error;
|
||||
AnswerInfo info;
|
||||
uint16_t offset;
|
||||
uint16_t length;
|
||||
uint16_t endOffset;
|
||||
OffsetRange offsetRange;
|
||||
AnswerTlv answerTlv;
|
||||
|
||||
if (Tlv::Find<QueryIdTlv>(aRequest, info.mQueryId) == kErrorNone)
|
||||
@@ -550,14 +548,14 @@ void Server::PrepareAndSendAnswers(const Ip6::Address &aDestination, const Messa
|
||||
|
||||
SuccessOrExit(error = AllocateAnswer(answer, info));
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffset(aRequest, Tlv::kTypeList, offset, length));
|
||||
endOffset = offset + length;
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRequest, Tlv::kTypeList, offsetRange));
|
||||
|
||||
for (; offset < endOffset; offset++)
|
||||
while (!offsetRange.IsEmpty())
|
||||
{
|
||||
uint8_t tlvType;
|
||||
|
||||
SuccessOrExit(error = aRequest.Read(offset, tlvType));
|
||||
SuccessOrExit(error = aRequest.Read(offsetRange, tlvType));
|
||||
offsetRange.AdvanceOffset(sizeof(tlvType));
|
||||
|
||||
switch (tlvType)
|
||||
{
|
||||
|
||||
@@ -379,8 +379,7 @@ exit:
|
||||
bool MeshDiag::ProcessChildrenIp6AddrsAnswer(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
bool didPorcess = false;
|
||||
uint16_t offset;
|
||||
uint16_t endOffset;
|
||||
OffsetRange offsetRange;
|
||||
ChildIp6AddressListTlvValue tlvValue;
|
||||
Ip6AddrIterator ip6AddrIterator;
|
||||
|
||||
@@ -388,11 +387,11 @@ bool MeshDiag::ProcessChildrenIp6AddrsAnswer(Coap::Message &aMessage, const Ip6:
|
||||
|
||||
while (true)
|
||||
{
|
||||
SuccessOrExit(Tlv::FindTlvValueStartEndOffsets(aMessage, ChildIp6AddressListTlv::kType, offset, endOffset));
|
||||
SuccessOrExit(Tlv::FindTlvValueOffsetRange(aMessage, ChildIp6AddressListTlv::kType, offsetRange));
|
||||
|
||||
didPorcess = true;
|
||||
|
||||
if (offset == endOffset)
|
||||
if (offsetRange.IsEmpty())
|
||||
{
|
||||
// We reached end of the list
|
||||
mState = kStateIdle;
|
||||
@@ -404,13 +403,11 @@ bool MeshDiag::ProcessChildrenIp6AddrsAnswer(Coap::Message &aMessage, const Ip6:
|
||||
// Read the `ChildIp6AddressListTlvValue` (which contains the
|
||||
// child RLOC16) and then prepare the `Ip6AddrIterator`.
|
||||
|
||||
VerifyOrExit(offset + sizeof(tlvValue) <= endOffset);
|
||||
IgnoreError(aMessage.Read(offset, tlvValue));
|
||||
offset += sizeof(tlvValue);
|
||||
SuccessOrExit(aMessage.Read(offsetRange, tlvValue));
|
||||
offsetRange.AdvanceOffset(sizeof(tlvValue));
|
||||
|
||||
ip6AddrIterator.mMessage = &aMessage;
|
||||
ip6AddrIterator.mCurOffset = offset;
|
||||
ip6AddrIterator.mEndOffset = endOffset;
|
||||
ip6AddrIterator.mMessage = &aMessage;
|
||||
ip6AddrIterator.mOffsetRange = offsetRange;
|
||||
|
||||
mQueryChildrenIp6Addrs.mCallback.InvokeIfSet(kErrorPending, tlvValue.GetRloc16(), &ip6AddrIterator);
|
||||
|
||||
@@ -418,7 +415,7 @@ bool MeshDiag::ProcessChildrenIp6AddrsAnswer(Coap::Message &aMessage, const Ip6:
|
||||
// callback.
|
||||
VerifyOrExit(mState == kStateQueryChildrenIp6Addrs);
|
||||
|
||||
aMessage.SetOffset(endOffset);
|
||||
aMessage.SetOffset(offsetRange.GetEndOffset());
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -531,7 +528,7 @@ Error MeshDiag::Ip6AddrIterator::InitFrom(const Message &aMessage)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aMessage, Ip6AddressListTlv::kType, mCurOffset, mEndOffset));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Ip6AddressListTlv::kType, mOffsetRange));
|
||||
mMessage = &aMessage;
|
||||
|
||||
exit:
|
||||
@@ -543,10 +540,9 @@ Error MeshDiag::Ip6AddrIterator::GetNextAddress(Ip6::Address &aAddress)
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
|
||||
VerifyOrExit(mCurOffset + sizeof(Ip6::Address) <= mEndOffset, error = kErrorNotFound);
|
||||
|
||||
IgnoreError(mMessage->Read(mCurOffset, aAddress));
|
||||
mCurOffset += sizeof(Ip6::Address);
|
||||
VerifyOrExit(mMessage->Read(mOffsetRange, aAddress) == kErrorNone, error = kErrorNotFound);
|
||||
mOffsetRange.AdvanceOffset(sizeof(Ip6::Address));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -559,7 +555,8 @@ Error MeshDiag::ChildIterator::InitFrom(const Message &aMessage, uint16_t aParen
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aMessage, ChildTableTlv::kType, mCurOffset, mEndOffset));
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, ChildTableTlv::kType, mOffsetRange));
|
||||
|
||||
mMessage = &aMessage;
|
||||
mParentRloc16 = aParentRloc16;
|
||||
|
||||
@@ -573,10 +570,9 @@ Error MeshDiag::ChildIterator::GetNextChildInfo(ChildInfo &aChildInfo)
|
||||
ChildTableEntry entry;
|
||||
|
||||
VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
|
||||
VerifyOrExit(mCurOffset + sizeof(ChildTableEntry) <= mEndOffset, error = kErrorNotFound);
|
||||
|
||||
IgnoreError(mMessage->Read(mCurOffset, entry));
|
||||
mCurOffset += sizeof(ChildTableEntry);
|
||||
VerifyOrExit(mMessage->Read(mOffsetRange, entry) == kErrorNone, error = kErrorNotFound);
|
||||
mOffsetRange.AdvanceOffset(sizeof(ChildTableEntry));
|
||||
|
||||
aChildInfo.mRloc16 = mParentRloc16 + entry.GetChildId();
|
||||
entry.GetMode().Get(aChildInfo.mMode);
|
||||
|
||||
@@ -105,8 +105,7 @@ public:
|
||||
Error InitFrom(const Message &aMessage);
|
||||
|
||||
const Message *mMessage;
|
||||
uint16_t mCurOffset;
|
||||
uint16_t mEndOffset;
|
||||
OffsetRange mOffsetRange;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -153,8 +152,7 @@ public:
|
||||
Error InitFrom(const Message &aMessage, uint16_t aParentRloc16);
|
||||
|
||||
const Message *mMessage;
|
||||
uint16_t mCurOffset;
|
||||
uint16_t mEndOffset;
|
||||
OffsetRange mOffsetRange;
|
||||
uint16_t mParentRloc16;
|
||||
};
|
||||
|
||||
|
||||
@@ -207,6 +207,7 @@ ot_unit_test(ndproxy_table)
|
||||
ot_unit_test(netif)
|
||||
ot_unit_test(network_data)
|
||||
ot_unit_test(network_name)
|
||||
ot_unit_test(offset_range)
|
||||
ot_unit_test(pool)
|
||||
ot_unit_test(power_calibration)
|
||||
ot_unit_test(priority_queue)
|
||||
|
||||
@@ -103,6 +103,7 @@ void TestIphcVector::GetUncompressedStream(Message &aMessage)
|
||||
static void Init(void)
|
||||
{
|
||||
otMeshLocalPrefix meshLocalPrefix = {{0xfd, 0x00, 0xca, 0xfe, 0xfa, 0xce, 0x12, 0x34}};
|
||||
OffsetRange offsetRange;
|
||||
|
||||
sInstance->Get<Mle::MleRouter>().SetMeshLocalPrefix(static_cast<Ip6::NetworkPrefix &>(meshLocalPrefix));
|
||||
|
||||
@@ -127,8 +128,10 @@ static void Init(void)
|
||||
|
||||
SuccessOrQuit(message->AppendBytes(mockNetworkData, sizeof(mockNetworkData)));
|
||||
|
||||
offsetRange.Init(2, 0x20);
|
||||
|
||||
IgnoreError(
|
||||
sInstance->Get<NetworkData::Leader>().SetNetworkData(0, 0, NetworkData::kStableSubset, *message, 2, 0x20));
|
||||
sInstance->Get<NetworkData::Leader>().SetNetworkData(0, 0, NetworkData::kStableSubset, *message, offsetRange));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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.
|
||||
*/
|
||||
|
||||
#include "common/message.hpp"
|
||||
#include "common/offset_range.hpp"
|
||||
#include "instance/instance.hpp"
|
||||
|
||||
#include "test_platform.h"
|
||||
#include "test_util.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
void TestOffsetRange(void)
|
||||
{
|
||||
Instance *instance;
|
||||
Message *message;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
instance = testInitInstance();
|
||||
VerifyOrQuit(instance != nullptr);
|
||||
|
||||
// Empty `OffsetRange`
|
||||
|
||||
offsetRange.Clear();
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 0);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 0);
|
||||
VerifyOrQuit(offsetRange.IsEmpty());
|
||||
|
||||
offsetRange.ShrinkLength(10);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 0);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 0);
|
||||
VerifyOrQuit(offsetRange.IsEmpty());
|
||||
|
||||
offsetRange.AdvanceOffset(20);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 0);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 0);
|
||||
VerifyOrQuit(offsetRange.IsEmpty());
|
||||
|
||||
// Empty `OffsetRange` with non-zero starting offset
|
||||
|
||||
offsetRange.Init(100, 0);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 100);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 100);
|
||||
VerifyOrQuit(offsetRange.IsEmpty());
|
||||
|
||||
offsetRange.ShrinkLength(10);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 100);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 100);
|
||||
VerifyOrQuit(offsetRange.IsEmpty());
|
||||
|
||||
offsetRange.AdvanceOffset(20);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 100);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 100);
|
||||
VerifyOrQuit(offsetRange.IsEmpty());
|
||||
|
||||
// Non-empty `OffsetRange`
|
||||
|
||||
offsetRange.Init(200, 10);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 200);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 10);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 210);
|
||||
VerifyOrQuit(!offsetRange.IsEmpty());
|
||||
VerifyOrQuit(offsetRange.Contains(10));
|
||||
VerifyOrQuit(!offsetRange.Contains(11));
|
||||
|
||||
offsetRange.ShrinkLength(10);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 200);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 10);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 210);
|
||||
|
||||
offsetRange.ShrinkLength(20);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 200);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 10);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 210);
|
||||
|
||||
offsetRange.ShrinkLength(5);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 200);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 5);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 205);
|
||||
VerifyOrQuit(!offsetRange.Contains(10));
|
||||
VerifyOrQuit(!offsetRange.Contains(6));
|
||||
VerifyOrQuit(offsetRange.Contains(5));
|
||||
|
||||
offsetRange.AdvanceOffset(4);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 204);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 1);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 205);
|
||||
VerifyOrQuit(!offsetRange.IsEmpty());
|
||||
VerifyOrQuit(offsetRange.Contains(1));
|
||||
VerifyOrQuit(!offsetRange.Contains(2));
|
||||
|
||||
offsetRange.AdvanceOffset(1);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 205);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 205);
|
||||
VerifyOrQuit(offsetRange.IsEmpty());
|
||||
|
||||
// `InitFromRange()`
|
||||
|
||||
offsetRange.InitFromRange(300, 400);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 300);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 100);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 400);
|
||||
VerifyOrQuit(!offsetRange.IsEmpty());
|
||||
VerifyOrQuit(offsetRange.Contains(100));
|
||||
VerifyOrQuit(!offsetRange.Contains(101));
|
||||
|
||||
offsetRange.AdvanceOffset(101);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 400);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 400);
|
||||
VerifyOrQuit(offsetRange.IsEmpty());
|
||||
|
||||
// Init from a `Message` from offset or full length
|
||||
|
||||
message = instance->Get<MessagePool>().Allocate(Message::kTypeOther);
|
||||
VerifyOrQuit(message != nullptr);
|
||||
|
||||
SuccessOrQuit(message->SetLength(120));
|
||||
VerifyOrQuit(message->GetOffset() == 0);
|
||||
|
||||
offsetRange.InitFromMessageOffsetToEnd(*message);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 0);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 120);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 120);
|
||||
|
||||
offsetRange.InitFromMessageFullLength(*message);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 0);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 120);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 120);
|
||||
|
||||
message->SetOffset(40);
|
||||
VerifyOrQuit(message->GetOffset() == 40);
|
||||
|
||||
offsetRange.InitFromMessageOffsetToEnd(*message);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 40);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 80);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 120);
|
||||
|
||||
offsetRange.InitFromMessageFullLength(*message);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == 0);
|
||||
VerifyOrQuit(offsetRange.GetLength() == 120);
|
||||
VerifyOrQuit(offsetRange.GetEndOffset() == 120);
|
||||
|
||||
message->Free();
|
||||
testFreeInstance(instance);
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ot::TestOffsetRange();
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
+23
-23
@@ -45,7 +45,7 @@ void TestTlv(void)
|
||||
Tlv tlv;
|
||||
ExtendedTlv extTlv;
|
||||
uint16_t offset;
|
||||
uint16_t valueOffset;
|
||||
OffsetRange offsetRange;
|
||||
uint16_t length;
|
||||
uint8_t buffer[4];
|
||||
|
||||
@@ -57,7 +57,7 @@ void TestTlv(void)
|
||||
VerifyOrQuit(message->GetOffset() == 0);
|
||||
VerifyOrQuit(message->GetLength() == 0);
|
||||
|
||||
VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 1, valueOffset, length) == kErrorNotFound);
|
||||
VerifyOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 1, offsetRange) == kErrorNotFound);
|
||||
VerifyOrQuit(Tlv::ReadTlvValue(*message, 0, buffer, 1) == kErrorParse);
|
||||
|
||||
// Add an empty TLV with type 1 and check that we can find it
|
||||
@@ -68,9 +68,9 @@ void TestTlv(void)
|
||||
tlv.SetLength(0);
|
||||
SuccessOrQuit(message->Append(tlv));
|
||||
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 1, valueOffset, length));
|
||||
VerifyOrQuit(valueOffset == sizeof(Tlv));
|
||||
VerifyOrQuit(length == 0);
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 1, offsetRange));
|
||||
VerifyOrQuit(offsetRange.GetOffset() == sizeof(Tlv));
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 0));
|
||||
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
|
||||
|
||||
@@ -82,9 +82,9 @@ void TestTlv(void)
|
||||
extTlv.SetLength(0);
|
||||
SuccessOrQuit(message->Append(extTlv));
|
||||
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 2, valueOffset, length));
|
||||
VerifyOrQuit(valueOffset == offset + sizeof(ExtendedTlv));
|
||||
VerifyOrQuit(length == 0);
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 2, offsetRange));
|
||||
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(ExtendedTlv));
|
||||
VerifyOrQuit(offsetRange.GetLength() == 0);
|
||||
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 0));
|
||||
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
|
||||
|
||||
@@ -97,9 +97,9 @@ void TestTlv(void)
|
||||
SuccessOrQuit(message->Append(tlv));
|
||||
SuccessOrQuit(message->Append<uint8_t>(0xff));
|
||||
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 3, valueOffset, length));
|
||||
VerifyOrQuit(valueOffset == offset + sizeof(Tlv));
|
||||
VerifyOrQuit(length == 1);
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 3, offsetRange));
|
||||
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(Tlv));
|
||||
VerifyOrQuit(offsetRange.GetLength() == 1);
|
||||
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1));
|
||||
VerifyOrQuit(buffer[0] == 0x0ff);
|
||||
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2) == kErrorParse);
|
||||
@@ -114,9 +114,9 @@ void TestTlv(void)
|
||||
SuccessOrQuit(message->Append<uint8_t>(0x12));
|
||||
SuccessOrQuit(message->Append<uint8_t>(0x34));
|
||||
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 4, valueOffset, length));
|
||||
VerifyOrQuit(valueOffset == offset + sizeof(ExtendedTlv));
|
||||
VerifyOrQuit(length == 2);
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 4, offsetRange));
|
||||
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(ExtendedTlv));
|
||||
VerifyOrQuit(offsetRange.GetLength() == 2);
|
||||
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1));
|
||||
VerifyOrQuit(buffer[0] == 0x12);
|
||||
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2));
|
||||
@@ -132,15 +132,15 @@ void TestTlv(void)
|
||||
tlv.SetLength(1);
|
||||
SuccessOrQuit(message->Append(tlv));
|
||||
|
||||
VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 5, valueOffset, length) != kErrorNone);
|
||||
VerifyOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 5, offsetRange) != kErrorNone);
|
||||
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 0) == kErrorParse);
|
||||
|
||||
// Add the missing value.
|
||||
SuccessOrQuit(message->Append<uint8_t>(0xaa));
|
||||
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 5, valueOffset, length));
|
||||
VerifyOrQuit(valueOffset == offset + sizeof(Tlv));
|
||||
VerifyOrQuit(length == 1);
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 5, offsetRange));
|
||||
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(Tlv));
|
||||
VerifyOrQuit(offsetRange.GetLength() == 1);
|
||||
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1));
|
||||
VerifyOrQuit(buffer[0] == 0xaa);
|
||||
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2) == kErrorParse);
|
||||
@@ -154,14 +154,14 @@ void TestTlv(void)
|
||||
SuccessOrQuit(message->Append(extTlv));
|
||||
SuccessOrQuit(message->Append<uint8_t>(0xbb));
|
||||
|
||||
VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 6, valueOffset, length) != kErrorNone);
|
||||
VerifyOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 6, offsetRange) != kErrorNone);
|
||||
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
|
||||
|
||||
SuccessOrQuit(message->Append<uint8_t>(0xcc));
|
||||
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 6, valueOffset, length) != kErrorNone);
|
||||
VerifyOrQuit(valueOffset == offset + sizeof(ExtendedTlv));
|
||||
VerifyOrQuit(length == 2);
|
||||
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 6, offsetRange) != kErrorNone);
|
||||
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(ExtendedTlv));
|
||||
VerifyOrQuit(offsetRange.GetLength() == 2);
|
||||
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2));
|
||||
VerifyOrQuit(buffer[0] == 0xbb);
|
||||
VerifyOrQuit(buffer[1] == 0xcc);
|
||||
@@ -176,7 +176,7 @@ void TestTlv(void)
|
||||
SuccessOrQuit(message->Append(extTlv));
|
||||
SuccessOrQuit(message->Append<uint8_t>(0x11));
|
||||
|
||||
VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 7, valueOffset, length) != kErrorNone);
|
||||
VerifyOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 7, offsetRange) != kErrorNone);
|
||||
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
|
||||
|
||||
message->Free();
|
||||
|
||||
Reference in New Issue
Block a user