mirror of
https://github.com/espressif/openthread.git
synced 2026-08-12 05:37:46 +00:00
[core] adding FrameData class for parsing frames (#7892)
This commit adds a new class `FrameData` which is a sub-class of `Data` (acts as a wrapper over a buffer pointer and a length). It is used in `MeshForwarder` and `Lowpan` to simplify the method calls (can pass `FrameData` instance instead of pointer and length). It also provides helper methods for parsing the frame content (e.g., reading `uint16/32` value assuming big or little endian encoding). When read successfully, the `FrameData` is updated to skip over the read content. These methods help simplify `Lowpan` parsing and decompression code. In particular the `Lowpan` methods now directly update the passed-in `FrameData` to skip over the parsed header portion (instead of returning the parsed header length).
This commit is contained in:
@@ -231,6 +231,7 @@ LOCAL_SRC_FILES := \
|
||||
src/core/common/crc16.cpp \
|
||||
src/core/common/data.cpp \
|
||||
src/core/common/error.cpp \
|
||||
src/core/common/frame_data.cpp \
|
||||
src/core/common/heap.cpp \
|
||||
src/core/common/heap_data.cpp \
|
||||
src/core/common/heap_string.cpp \
|
||||
|
||||
@@ -397,6 +397,8 @@ openthread_core_files = [
|
||||
"common/error.cpp",
|
||||
"common/error.hpp",
|
||||
"common/extension.hpp",
|
||||
"common/frame_data.cpp",
|
||||
"common/frame_data.hpp",
|
||||
"common/heap.cpp",
|
||||
"common/heap.hpp",
|
||||
"common/heap_allocatable.hpp",
|
||||
|
||||
@@ -97,6 +97,7 @@ set(COMMON_SOURCES
|
||||
common/crc16.cpp
|
||||
common/data.cpp
|
||||
common/error.cpp
|
||||
common/frame_data.cpp
|
||||
common/heap.cpp
|
||||
common/heap_data.cpp
|
||||
common/heap_string.cpp
|
||||
|
||||
@@ -187,6 +187,7 @@ SOURCES_COMMON = \
|
||||
common/crc16.cpp \
|
||||
common/data.cpp \
|
||||
common/error.cpp \
|
||||
common/frame_data.cpp \
|
||||
common/heap.cpp \
|
||||
common/heap_data.cpp \
|
||||
common/heap_string.cpp \
|
||||
@@ -437,6 +438,7 @@ HEADERS_COMMON = \
|
||||
common/equatable.hpp \
|
||||
common/error.hpp \
|
||||
common/extension.hpp \
|
||||
common/frame_data.hpp \
|
||||
common/heap.hpp \
|
||||
common/heap_allocatable.hpp \
|
||||
common/heap_array.hpp \
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2022, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes implementation of `FrameData`.
|
||||
*/
|
||||
|
||||
#include "frame_data.hpp"
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
Error FrameData::ReadUint8(uint8_t &aUint8)
|
||||
{
|
||||
return ReadBytes(&aUint8, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
Error FrameData::ReadBigEndianUint16(uint16_t &aUint16)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = ReadBytes(&aUint16, sizeof(uint16_t)));
|
||||
aUint16 = Encoding::BigEndian::HostSwap16(aUint16);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error FrameData::ReadBigEndianUint32(uint32_t &aUint32)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = ReadBytes(&aUint32, sizeof(uint32_t)));
|
||||
aUint32 = Encoding::BigEndian::HostSwap32(aUint32);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error FrameData::ReadLittleEndianUint16(uint16_t &aUint16)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = ReadBytes(&aUint16, sizeof(uint16_t)));
|
||||
aUint16 = Encoding::LittleEndian::HostSwap16(aUint16);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error FrameData::ReadLittleEndianUint32(uint32_t &aUint32)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = ReadBytes(&aUint32, sizeof(uint32_t)));
|
||||
aUint32 = Encoding::LittleEndian::HostSwap32(aUint32);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error FrameData::ReadBytes(void *aBuffer, uint16_t aLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(CanRead(aLength), error = kErrorParse);
|
||||
memcpy(aBuffer, GetBytes(), aLength);
|
||||
SkipOver(aLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void FrameData::SkipOver(uint16_t aLength)
|
||||
{
|
||||
Init(GetBytes() + aLength, GetLength() - aLength);
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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 `FrameData`.
|
||||
*/
|
||||
|
||||
#ifndef FRAME_DATA_HPP_
|
||||
#define FRAME_DATA_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include "common/data.hpp"
|
||||
#include "common/type_traits.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
/**
|
||||
* This class represents a frame `Data` which is simply a wrapper over a pointer to a buffer with a given frame length.
|
||||
*
|
||||
* It provide helper method to parse the content. As data is parsed and read, the `FrameData` is updated to skip over
|
||||
* the read content.
|
||||
*
|
||||
*/
|
||||
class FrameData : public Data<kWithUint16Length>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method indicates whether or not there are enough bytes remaining in the `FrameData` to read a given number
|
||||
* of bytes.
|
||||
*
|
||||
* @param[in] aLength The read length to check.
|
||||
*
|
||||
* @retval TRUE There are enough remaining bytes to read @p aLength bytes.
|
||||
* @retval FALSE There are not enough remaining bytes to read @p aLength bytes.
|
||||
*
|
||||
*/
|
||||
bool CanRead(uint16_t aLength) const { return GetLength() >= aLength; }
|
||||
|
||||
/**
|
||||
* This method reads an `uint8_t` value from the `FrameData`.
|
||||
*
|
||||
* If read successfully, the `FrameData` is updated to skip over the read content.
|
||||
*
|
||||
* @param[out] aUint8 A reference to an `uint8_t` to return the read value.
|
||||
*
|
||||
* @retval kErrorNone Successfully read `uint8_t` value and skipped over it.
|
||||
* @retval kErrorParse Not enough bytes remaining to read.
|
||||
*
|
||||
*/
|
||||
Error ReadUint8(uint8_t &aUint8);
|
||||
|
||||
/**
|
||||
* This method reads an `uint16_t` value assuming big endian encoding from the `FrameData`.
|
||||
*
|
||||
* If read successfully, the `FrameData` is updated to skip over the read content.
|
||||
*
|
||||
* @param[out] aUint16 A reference to an `uint16_t` to return the read value.
|
||||
*
|
||||
* @retval kErrorNone Successfully read `uint16_t` value and skipped over it.
|
||||
* @retval kErrorParse Not enough bytes remaining to read.
|
||||
*
|
||||
*/
|
||||
Error ReadBigEndianUint16(uint16_t &aUint16);
|
||||
|
||||
/**
|
||||
* This method reads an `uint32_t` value assuming big endian encoding from the `FrameData`.
|
||||
*
|
||||
* If read successfully, the `FrameData` is updated to skip over the read content.
|
||||
*
|
||||
* @param[out] aUint32 A reference to an `uint32_t` to return the read value.
|
||||
*
|
||||
* @retval kErrorNone Successfully read `uint32_t` value and skipped over it.
|
||||
* @retval kErrorParse Not enough bytes remaining to read.
|
||||
*
|
||||
*/
|
||||
Error ReadBigEndianUint32(uint32_t &aUint32);
|
||||
|
||||
/**
|
||||
* This method reads an `uint16_t` value assuming little endian encoding from the `FrameData`.
|
||||
*
|
||||
* If read successfully, the `FrameData` is updated to skip over the read content.
|
||||
*
|
||||
* @param[out] aUint16 A reference to an `uint16_t` to return the read value.
|
||||
*
|
||||
* @retval kErrorNone Successfully read `uint16_t` value and skipped over it.
|
||||
* @retval kErrorParse Not enough bytes remaining to read.
|
||||
*
|
||||
*/
|
||||
Error ReadLittleEndianUint16(uint16_t &aUint16);
|
||||
|
||||
/**
|
||||
* This method reads an `uint32_t` value assuming little endian encoding from the `FrameData`.
|
||||
*
|
||||
* If read successfully, the `FrameData` is updated to skip over the read content.
|
||||
*
|
||||
* @param[out] aUint32 A reference to an `uint32_t` to return the read value.
|
||||
*
|
||||
* @retval kErrorNone Successfully read `uint32_t` value and skipped over it.
|
||||
* @retval kErrorParse Not enough bytes remaining to read.
|
||||
*
|
||||
*/
|
||||
Error ReadLittleEndianUint32(uint32_t &aUint32);
|
||||
|
||||
/**
|
||||
* This method reads a given number of bytes from the `FrameData`.
|
||||
*
|
||||
* If read successfully, the `FrameData` is updated to skip over the read content.
|
||||
*
|
||||
* @param[out] aBuffer The buffer to copy the read bytes into.
|
||||
* @param[in] aLength Number of bytes to read.
|
||||
*
|
||||
* @retval kErrorNone Successfully read @p aLength bytes into @p aBuffer and skipped over them.
|
||||
* @retval kErrorParse Not enough bytes remaining to read @p aLength.
|
||||
*
|
||||
*/
|
||||
Error ReadBytes(void *aBuffer, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* This template method reads an object from the `FrameData`.
|
||||
*
|
||||
* @tparam ObjectType The object type to read from the message.
|
||||
*
|
||||
* @param[out] aObject A reference to the object to read into.
|
||||
*
|
||||
* @retval kErrorNone Successfully read @p aObject and skipped over the read content.
|
||||
* @retval kErrorParse Not enough bytes remaining to read the entire object.
|
||||
*
|
||||
*/
|
||||
template <typename ObjectType> Error Read(ObjectType &aObject)
|
||||
{
|
||||
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
|
||||
|
||||
return ReadBytes(&aObject, sizeof(ObjectType));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method skips over a given number of bytes from `FrameData`.
|
||||
*
|
||||
* The caller MUST make sure that the @p aLength is smaller than current data length. Otherwise the behavior of
|
||||
* this method is undefined.
|
||||
*
|
||||
* @param[in] aLength The length (number of bytes) to skip over.
|
||||
*
|
||||
*/
|
||||
void SkipOver(uint16_t aLength);
|
||||
};
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // FRAME_DATA_HPP_
|
||||
@@ -662,6 +662,24 @@ public:
|
||||
return AppendBytes(&aObject, sizeof(ObjectType));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method appends bytes from a given `Data` instance to the end of the message.
|
||||
*
|
||||
* On success, this method grows the message by the size of the appended data.
|
||||
*
|
||||
* @tparam kDataLengthType Determines the data length type (`uint8_t` or `uint16_t`).
|
||||
*
|
||||
* @param[in] aData A reference to `Data` to append to the message.
|
||||
*
|
||||
* @retval kErrorNone Successfully appended the bytes from @p aData.
|
||||
* @retval kErrorNoBufs Insufficient available buffers to grow the message.
|
||||
*
|
||||
*/
|
||||
template <DataLengthType kDataLengthType> Error AppendData(const Data<kDataLengthType> &aData)
|
||||
{
|
||||
return AppendBytes(aData.GetBytes(), aData.GetLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method reads bytes from the message.
|
||||
*
|
||||
@@ -807,6 +825,23 @@ public:
|
||||
WriteBytes(aOffset, &aObject, sizeof(ObjectType));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method writes bytes from a given `Data` instance to the message.
|
||||
*
|
||||
* This method will not resize the message. The given data to write MUST fit within the existing message buffer
|
||||
* (from the given offset @p aOffset up to the message's length).
|
||||
*
|
||||
* @tparam kDataLengthType Determines the data length type (`uint8_t` or `uint16_t`).
|
||||
*
|
||||
* @param[in] aOffset Byte offset within the message to begin writing.
|
||||
* @param[in] aData The `Data` to write to the message.
|
||||
*
|
||||
*/
|
||||
template <DataLengthType kDataLengthType> void WriteData(uint16_t aOffset, const Data<kDataLengthType> &aData)
|
||||
{
|
||||
WriteBytes(aOffset, aData.GetBytes(), aData.GetLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method copies bytes from one message to another.
|
||||
*
|
||||
|
||||
+16
-26
@@ -1534,66 +1534,56 @@ Error Headers::DecompressFrom(const Message & aMessage,
|
||||
{
|
||||
static constexpr uint16_t kReadLength = Lowpan::FragmentHeader::kSubsequentFragmentHeaderSize + sizeof(Headers);
|
||||
|
||||
uint8_t frameBuffer[kReadLength];
|
||||
uint16_t frameLength;
|
||||
uint8_t frameBuffer[kReadLength];
|
||||
uint16_t frameLength;
|
||||
FrameData frameData;
|
||||
|
||||
frameLength = aMessage.ReadBytes(aOffset, frameBuffer, sizeof(frameBuffer));
|
||||
frameData.Init(frameBuffer, frameLength);
|
||||
|
||||
return DecompressFrom(frameBuffer, frameLength, aMacSource, aMacDest, aMessage.GetInstance());
|
||||
return DecompressFrom(frameData, aMacSource, aMacDest, aMessage.GetInstance());
|
||||
}
|
||||
|
||||
Error Headers::DecompressFrom(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
Error Headers::DecompressFrom(const FrameData & aFrameData,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
Instance & aInstance)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error = kErrorNone;
|
||||
FrameData frameData = aFrameData;
|
||||
Lowpan::FragmentHeader fragmentHeader;
|
||||
uint16_t fragmentHeaderLength;
|
||||
int headerLength;
|
||||
bool nextHeaderCompressed;
|
||||
|
||||
if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone)
|
||||
if (fragmentHeader.ParseFrom(frameData) == kErrorNone)
|
||||
{
|
||||
// Only the first fragment header is followed by a LOWPAN_IPHC header
|
||||
VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = kErrorNotFound);
|
||||
aFrame += fragmentHeaderLength;
|
||||
aFrameLength -= fragmentHeaderLength;
|
||||
}
|
||||
|
||||
VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = kErrorNotFound);
|
||||
headerLength = aInstance.Get<Lowpan::Lowpan>().DecompressBaseHeader(mIp6Header, nextHeaderCompressed, aMacSource,
|
||||
aMacDest, aFrame, aFrameLength);
|
||||
VerifyOrExit(Lowpan::Lowpan::IsLowpanHc(frameData), error = kErrorNotFound);
|
||||
|
||||
VerifyOrExit(headerLength > 0, error = kErrorParse);
|
||||
|
||||
aFrame += headerLength;
|
||||
aFrameLength -= headerLength;
|
||||
SuccessOrExit(error = aInstance.Get<Lowpan::Lowpan>().DecompressBaseHeader(mIp6Header, nextHeaderCompressed,
|
||||
aMacSource, aMacDest, frameData));
|
||||
|
||||
switch (mIp6Header.GetNextHeader())
|
||||
{
|
||||
case kProtoUdp:
|
||||
if (nextHeaderCompressed)
|
||||
{
|
||||
headerLength = aInstance.Get<Lowpan::Lowpan>().DecompressUdpHeader(mHeader.mUdp, aFrame, aFrameLength);
|
||||
VerifyOrExit(headerLength >= 0, error = kErrorParse);
|
||||
SuccessOrExit(error = aInstance.Get<Lowpan::Lowpan>().DecompressUdpHeader(mHeader.mUdp, frameData));
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(aFrameLength >= sizeof(Udp::Header), error = kErrorParse);
|
||||
mHeader.mUdp = *reinterpret_cast<const Udp::Header *>(aFrame);
|
||||
SuccessOrExit(error = frameData.Read(mHeader.mUdp));
|
||||
}
|
||||
break;
|
||||
|
||||
case kProtoTcp:
|
||||
VerifyOrExit(aFrameLength >= sizeof(Tcp::Header), error = kErrorParse);
|
||||
mHeader.mTcp = *reinterpret_cast<const Tcp::Header *>(aFrame);
|
||||
SuccessOrExit(error = frameData.Read(mHeader.mTcp));
|
||||
break;
|
||||
|
||||
case kProtoIcmp6:
|
||||
VerifyOrExit(aFrameLength >= sizeof(Icmp::Header), error = kErrorParse);
|
||||
mHeader.mIcmp = *reinterpret_cast<const Icmp::Header *>(aFrame);
|
||||
SuccessOrExit(error = frameData.Read(mHeader.mIcmp));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <openthread/udp.h>
|
||||
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/frame_data.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/log.hpp"
|
||||
#include "common/message.hpp"
|
||||
@@ -416,8 +417,7 @@ public:
|
||||
/**
|
||||
* This method decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
|
||||
*
|
||||
* @param[in] aFrame Buffer containig the lowpan frame.
|
||||
* @param[in] aFrameLength Number of bytes in @p aFrame.
|
||||
* @param[in] aFrameData The lowpan frame data.
|
||||
* @param[in] aMacSource The MAC source address.
|
||||
* @param[in] aMacDest The MAC destination address.
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
@@ -427,8 +427,7 @@ public:
|
||||
* @retval kErrorParse Failed to parse the headers.
|
||||
*
|
||||
*/
|
||||
Error DecompressFrom(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
Error DecompressFrom(const FrameData & aFrameData,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
Instance & aInstance);
|
||||
|
||||
+156
-185
@@ -655,26 +655,21 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
bool & aCompressedNextHeader,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
const uint8_t * aBuf,
|
||||
uint16_t aBufLength)
|
||||
Error Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
bool & aCompressedNextHeader,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
FrameData & aFrameData)
|
||||
{
|
||||
NetworkData::Leader &networkData = Get<NetworkData::Leader>();
|
||||
Error error = kErrorParse;
|
||||
const uint8_t * cur = aBuf;
|
||||
const uint8_t * end = aBuf + aBufLength;
|
||||
uint16_t hcCtl;
|
||||
uint8_t byte;
|
||||
Context srcContext, dstContext;
|
||||
bool srcContextValid = true, dstContextValid = true;
|
||||
uint8_t nextHeader;
|
||||
uint8_t * bytes;
|
||||
|
||||
VerifyOrExit(cur + 2 <= end);
|
||||
hcCtl = ReadUint16(cur);
|
||||
cur += 2;
|
||||
SuccessOrExit(aFrameData.ReadBigEndianUint16(hcCtl));
|
||||
|
||||
// check Dispatch bits
|
||||
VerifyOrExit((hcCtl & kHcDispatchMask) == kHcDispatch);
|
||||
@@ -685,19 +680,17 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
|
||||
if ((hcCtl & kHcContextId) != 0)
|
||||
{
|
||||
VerifyOrExit(cur < end);
|
||||
SuccessOrExit(aFrameData.ReadUint8(byte));
|
||||
|
||||
if (networkData.GetContext(cur[0] >> 4, srcContext) != kErrorNone)
|
||||
if (networkData.GetContext(byte >> 4, srcContext) != kErrorNone)
|
||||
{
|
||||
srcContextValid = false;
|
||||
}
|
||||
|
||||
if (networkData.GetContext(cur[0] & 0xf, dstContext) != kErrorNone)
|
||||
if (networkData.GetContext(byte & 0xf, dstContext) != kErrorNone)
|
||||
{
|
||||
dstContextValid = false;
|
||||
}
|
||||
|
||||
cur++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -711,34 +704,35 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
// Traffic Class and Flow Label
|
||||
if ((hcCtl & kHcTrafficFlowMask) != kHcTrafficFlow)
|
||||
{
|
||||
VerifyOrExit(cur < end);
|
||||
uint8_t *ip6HeaderBytes = reinterpret_cast<uint8_t *>(&aIp6Header);
|
||||
|
||||
bytes = reinterpret_cast<uint8_t *>(&aIp6Header);
|
||||
bytes[1] |= (cur[0] & 0xc0) >> 2;
|
||||
VerifyOrExit(aFrameData.GetLength() > 0);
|
||||
|
||||
ip6HeaderBytes[1] |= (aFrameData.GetBytes()[0] & 0xc0) >> 2;
|
||||
|
||||
if ((hcCtl & kHcTrafficClass) == 0)
|
||||
{
|
||||
bytes[0] |= (cur[0] >> 2) & 0x0f;
|
||||
bytes[1] |= (cur[0] << 6) & 0xc0;
|
||||
cur++;
|
||||
IgnoreError(aFrameData.ReadUint8(byte));
|
||||
ip6HeaderBytes[0] |= (byte >> 2) & 0x0f;
|
||||
ip6HeaderBytes[1] |= (byte << 6) & 0xc0;
|
||||
}
|
||||
|
||||
if ((hcCtl & kHcFlowLabel) == 0)
|
||||
{
|
||||
VerifyOrExit(cur + 3 <= end);
|
||||
bytes[1] |= cur[0] & 0x0f;
|
||||
bytes[2] |= cur[1];
|
||||
bytes[3] |= cur[2];
|
||||
cur += 3;
|
||||
VerifyOrExit(aFrameData.GetLength() >= 3);
|
||||
ip6HeaderBytes[1] |= aFrameData.GetBytes()[0] & 0x0f;
|
||||
ip6HeaderBytes[2] |= aFrameData.GetBytes()[1];
|
||||
ip6HeaderBytes[3] |= aFrameData.GetBytes()[2];
|
||||
aFrameData.SkipOver(3);
|
||||
}
|
||||
}
|
||||
|
||||
// Next Header
|
||||
if ((hcCtl & kHcNextHeader) == 0)
|
||||
{
|
||||
VerifyOrExit(cur < end);
|
||||
aIp6Header.SetNextHeader(cur[0]);
|
||||
cur++;
|
||||
SuccessOrExit(aFrameData.ReadUint8(byte));
|
||||
|
||||
aIp6Header.SetNextHeader(byte);
|
||||
aCompressedNextHeader = false;
|
||||
}
|
||||
else
|
||||
@@ -762,9 +756,8 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
break;
|
||||
|
||||
default:
|
||||
VerifyOrExit(cur < end);
|
||||
aIp6Header.SetHopLimit(cur[0]);
|
||||
cur++;
|
||||
SuccessOrExit(aFrameData.ReadUint8(byte));
|
||||
aIp6Header.SetHopLimit(byte);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -774,25 +767,19 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
case kHcSrcAddrMode0:
|
||||
if ((hcCtl & kHcSrcAddrContext) == 0)
|
||||
{
|
||||
VerifyOrExit(cur + sizeof(Ip6::Address) <= end);
|
||||
memcpy(&aIp6Header.GetSource(), cur, sizeof(aIp6Header.GetSource()));
|
||||
cur += sizeof(Ip6::Address);
|
||||
SuccessOrExit(aFrameData.Read(aIp6Header.GetSource()));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kHcSrcAddrMode1:
|
||||
VerifyOrExit(cur + Ip6::InterfaceIdentifier::kSize <= end);
|
||||
aIp6Header.GetSource().GetIid().SetBytes(cur);
|
||||
cur += Ip6::InterfaceIdentifier::kSize;
|
||||
SuccessOrExit(aFrameData.Read(aIp6Header.GetSource().GetIid()));
|
||||
break;
|
||||
|
||||
case kHcSrcAddrMode2:
|
||||
VerifyOrExit(cur + 2 <= end);
|
||||
aIp6Header.GetSource().mFields.m8[11] = 0xff;
|
||||
aIp6Header.GetSource().mFields.m8[12] = 0xfe;
|
||||
memcpy(aIp6Header.GetSource().mFields.m8 + 14, cur, 2);
|
||||
cur += 2;
|
||||
SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetSource().mFields.m8 + 14, 2));
|
||||
break;
|
||||
|
||||
case kHcSrcAddrMode3:
|
||||
@@ -821,23 +808,17 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
{
|
||||
case kHcDstAddrMode0:
|
||||
VerifyOrExit((hcCtl & kHcDstAddrContext) == 0);
|
||||
VerifyOrExit(cur + sizeof(Ip6::Address) <= end);
|
||||
memcpy(&aIp6Header.GetDestination(), cur, sizeof(aIp6Header.GetDestination()));
|
||||
cur += sizeof(Ip6::Address);
|
||||
SuccessOrExit(aFrameData.Read(aIp6Header.GetDestination()));
|
||||
break;
|
||||
|
||||
case kHcDstAddrMode1:
|
||||
VerifyOrExit(cur + Ip6::InterfaceIdentifier::kSize <= end);
|
||||
aIp6Header.GetDestination().GetIid().SetBytes(cur);
|
||||
cur += Ip6::InterfaceIdentifier::kSize;
|
||||
SuccessOrExit(aFrameData.Read(aIp6Header.GetDestination().GetIid()));
|
||||
break;
|
||||
|
||||
case kHcDstAddrMode2:
|
||||
VerifyOrExit(cur + 2 <= end);
|
||||
aIp6Header.GetDestination().mFields.m8[11] = 0xff;
|
||||
aIp6Header.GetDestination().mFields.m8[12] = 0xfe;
|
||||
memcpy(aIp6Header.GetDestination().mFields.m8 + 14, cur, 2);
|
||||
cur += 2;
|
||||
SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 14, 2));
|
||||
break;
|
||||
|
||||
case kHcDstAddrMode3:
|
||||
@@ -869,30 +850,22 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
switch (hcCtl & kHcDstAddrModeMask)
|
||||
{
|
||||
case kHcDstAddrMode0:
|
||||
VerifyOrExit(cur + sizeof(Ip6::Address) <= end);
|
||||
memcpy(aIp6Header.GetDestination().mFields.m8, cur, sizeof(Ip6::Address));
|
||||
cur += sizeof(Ip6::Address);
|
||||
SuccessOrExit(aFrameData.Read(aIp6Header.GetDestination()));
|
||||
break;
|
||||
|
||||
case kHcDstAddrMode1:
|
||||
VerifyOrExit(cur + 6 <= end);
|
||||
aIp6Header.GetDestination().mFields.m8[1] = cur[0];
|
||||
memcpy(aIp6Header.GetDestination().mFields.m8 + 11, cur + 1, 5);
|
||||
cur += 6;
|
||||
SuccessOrExit(aFrameData.ReadUint8(aIp6Header.GetDestination().mFields.m8[1]));
|
||||
SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 11, 5));
|
||||
break;
|
||||
|
||||
case kHcDstAddrMode2:
|
||||
VerifyOrExit(cur + 4 <= end);
|
||||
aIp6Header.GetDestination().mFields.m8[1] = cur[0];
|
||||
memcpy(aIp6Header.GetDestination().mFields.m8 + 13, cur + 1, 3);
|
||||
cur += 4;
|
||||
SuccessOrExit(aFrameData.ReadUint8(aIp6Header.GetDestination().mFields.m8[1]));
|
||||
SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 13, 3));
|
||||
break;
|
||||
|
||||
case kHcDstAddrMode3:
|
||||
VerifyOrExit(cur < end);
|
||||
aIp6Header.GetDestination().mFields.m8[1] = 0x02;
|
||||
aIp6Header.GetDestination().mFields.m8[15] = cur[0];
|
||||
cur++;
|
||||
aIp6Header.GetDestination().mFields.m8[1] = 0x02;
|
||||
SuccessOrExit(aFrameData.ReadUint8(aIp6Header.GetDestination().mFields.m8[15]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -901,14 +874,11 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
switch (hcCtl & kHcDstAddrModeMask)
|
||||
{
|
||||
case 0:
|
||||
VerifyOrExit(cur + 6 <= end);
|
||||
VerifyOrExit(dstContextValid);
|
||||
aIp6Header.GetDestination().mFields.m8[1] = cur[0];
|
||||
aIp6Header.GetDestination().mFields.m8[2] = cur[1];
|
||||
SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 1, 2));
|
||||
aIp6Header.GetDestination().mFields.m8[3] = dstContext.mPrefix.GetLength();
|
||||
memcpy(aIp6Header.GetDestination().mFields.m8 + 4, dstContext.mPrefix.GetBytes(), 8);
|
||||
memcpy(aIp6Header.GetDestination().mFields.m8 + 12, cur + 2, 4);
|
||||
cur += 6;
|
||||
SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 12, 4));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -919,54 +889,41 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
|
||||
if ((hcCtl & kHcNextHeader) != 0)
|
||||
{
|
||||
VerifyOrExit(cur < end);
|
||||
SuccessOrExit(DispatchToNextHeader(cur[0], nextHeader));
|
||||
VerifyOrExit(aFrameData.GetLength() > 0);
|
||||
SuccessOrExit(DispatchToNextHeader(*aFrameData.GetBytes(), nextHeader));
|
||||
aIp6Header.SetNextHeader(nextHeader);
|
||||
}
|
||||
|
||||
error = kErrorNone;
|
||||
|
||||
exit:
|
||||
return (error == kErrorNone) ? static_cast<int>(cur - aBuf) : -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength)
|
||||
Error Lowpan::DecompressExtensionHeader(Message &aMessage, FrameData &aFrameData)
|
||||
{
|
||||
Error error = kErrorParse;
|
||||
const uint8_t * cur = aBuf;
|
||||
const uint8_t * end = aBuf + aBufLength;
|
||||
uint8_t hdr[2];
|
||||
uint8_t len;
|
||||
uint8_t nextHeader;
|
||||
uint8_t ctl = cur[0];
|
||||
uint8_t padLength;
|
||||
Ip6::OptionPad1 optionPad1;
|
||||
Ip6::OptionPadN optionPadN;
|
||||
Error error = kErrorParse;
|
||||
uint8_t hdr[2];
|
||||
uint8_t len;
|
||||
uint8_t ctl;
|
||||
uint8_t padLength;
|
||||
|
||||
VerifyOrExit(cur < end);
|
||||
cur++;
|
||||
SuccessOrExit(aFrameData.ReadUint8(ctl));
|
||||
|
||||
// next header
|
||||
if (ctl & kExtHdrNextHeader)
|
||||
{
|
||||
VerifyOrExit(cur < end);
|
||||
SuccessOrExit(aFrameData.ReadUint8(len));
|
||||
|
||||
len = cur[0];
|
||||
cur++;
|
||||
|
||||
VerifyOrExit(cur + len <= end);
|
||||
SuccessOrExit(DispatchToNextHeader(cur[len], nextHeader));
|
||||
hdr[0] = static_cast<uint8_t>(nextHeader);
|
||||
VerifyOrExit(aFrameData.CanRead(len + 1));
|
||||
SuccessOrExit(DispatchToNextHeader(aFrameData.GetBytes()[len], hdr[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(cur + 2 <= end);
|
||||
SuccessOrExit(aFrameData.ReadUint8(hdr[0]));
|
||||
SuccessOrExit(aFrameData.ReadUint8(len));
|
||||
|
||||
hdr[0] = cur[0];
|
||||
len = cur[1];
|
||||
cur += 2;
|
||||
|
||||
VerifyOrExit(cur + len <= end);
|
||||
VerifyOrExit(aFrameData.CanRead(len));
|
||||
}
|
||||
|
||||
// length
|
||||
@@ -976,9 +933,9 @@ int Lowpan::DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, ui
|
||||
aMessage.MoveOffset(sizeof(hdr));
|
||||
|
||||
// payload
|
||||
SuccessOrExit(aMessage.AppendBytes(cur, len));
|
||||
SuccessOrExit(aMessage.AppendBytes(aFrameData.GetBytes(), len));
|
||||
aMessage.MoveOffset(len);
|
||||
cur += len;
|
||||
aFrameData.SkipOver(len);
|
||||
|
||||
// The RFC6282 says: "The trailing Pad1 or PadN option MAY be elided by the compressor.
|
||||
// A decompressor MUST ensure that the containing header is padded out to a multiple of 8 octets
|
||||
@@ -989,11 +946,15 @@ int Lowpan::DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, ui
|
||||
{
|
||||
if (padLength == 1)
|
||||
{
|
||||
Ip6::OptionPad1 optionPad1;
|
||||
|
||||
optionPad1.Init();
|
||||
SuccessOrExit(aMessage.AppendBytes(&optionPad1, padLength));
|
||||
}
|
||||
else
|
||||
{
|
||||
Ip6::OptionPadN optionPadN;
|
||||
|
||||
optionPadN.Init(padLength);
|
||||
SuccessOrExit(aMessage.AppendBytes(&optionPadN, padLength));
|
||||
}
|
||||
@@ -1004,163 +965,145 @@ int Lowpan::DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, ui
|
||||
error = kErrorNone;
|
||||
|
||||
exit:
|
||||
return (error == kErrorNone) ? static_cast<int>(cur - aBuf) : -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, const uint8_t *aBuf, uint16_t aBufLength)
|
||||
Error Lowpan::DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, FrameData &aFrameData)
|
||||
{
|
||||
Error error = kErrorParse;
|
||||
const uint8_t *cur = aBuf;
|
||||
const uint8_t *end = aBuf + aBufLength;
|
||||
uint8_t udpCtl;
|
||||
Error error = kErrorParse;
|
||||
uint8_t udpCtl;
|
||||
uint8_t byte;
|
||||
uint16_t srcPort = 0;
|
||||
uint16_t dstPort = 0;
|
||||
|
||||
VerifyOrExit(cur < end);
|
||||
udpCtl = cur[0];
|
||||
cur++;
|
||||
SuccessOrExit(aFrameData.ReadUint8(udpCtl));
|
||||
|
||||
VerifyOrExit((udpCtl & kUdpDispatchMask) == kUdpDispatch);
|
||||
|
||||
memset(&aUdpHeader, 0, sizeof(aUdpHeader));
|
||||
aUdpHeader.Clear();
|
||||
|
||||
// source and dest ports
|
||||
switch (udpCtl & kUdpPortMask)
|
||||
{
|
||||
case 0:
|
||||
VerifyOrExit(cur + 4 <= end);
|
||||
aUdpHeader.SetSourcePort(ReadUint16(cur));
|
||||
aUdpHeader.SetDestinationPort(ReadUint16(cur + 2));
|
||||
cur += 4;
|
||||
SuccessOrExit(aFrameData.ReadBigEndianUint16(srcPort));
|
||||
SuccessOrExit(aFrameData.ReadBigEndianUint16(dstPort));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
VerifyOrExit(cur + 3 <= end);
|
||||
aUdpHeader.SetSourcePort(ReadUint16(cur));
|
||||
aUdpHeader.SetDestinationPort(0xf000 | cur[2]);
|
||||
cur += 3;
|
||||
SuccessOrExit(aFrameData.ReadBigEndianUint16(srcPort));
|
||||
SuccessOrExit(aFrameData.ReadUint8(byte));
|
||||
dstPort = (0xf000 | byte);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
VerifyOrExit(cur + 3 <= end);
|
||||
aUdpHeader.SetSourcePort(0xf000 | cur[0]);
|
||||
aUdpHeader.SetDestinationPort(ReadUint16(cur + 1));
|
||||
cur += 3;
|
||||
SuccessOrExit(aFrameData.ReadUint8(byte));
|
||||
srcPort = (0xf000 | byte);
|
||||
SuccessOrExit(aFrameData.ReadBigEndianUint16(dstPort));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
VerifyOrExit(cur < end);
|
||||
aUdpHeader.SetSourcePort(0xf0b0 | (cur[0] >> 4));
|
||||
aUdpHeader.SetDestinationPort(0xf0b0 | (cur[0] & 0xf));
|
||||
cur++;
|
||||
SuccessOrExit(aFrameData.ReadUint8(byte));
|
||||
srcPort = (0xf0b0 | (byte >> 4));
|
||||
dstPort = (0xf0b0 | (byte & 0xf));
|
||||
break;
|
||||
}
|
||||
|
||||
// checksum
|
||||
aUdpHeader.SetSourcePort(srcPort);
|
||||
aUdpHeader.SetDestinationPort(dstPort);
|
||||
|
||||
if ((udpCtl & kUdpChecksum) != 0)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(cur + 2 <= end);
|
||||
aUdpHeader.SetChecksum(ReadUint16(cur));
|
||||
cur += 2;
|
||||
uint16_t checksum;
|
||||
|
||||
SuccessOrExit(aFrameData.ReadBigEndianUint16(checksum));
|
||||
aUdpHeader.SetChecksum(checksum);
|
||||
}
|
||||
|
||||
error = kErrorNone;
|
||||
|
||||
exit:
|
||||
return (error == kErrorNone) ? static_cast<int>(cur - aBuf) : -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength)
|
||||
Error Lowpan::DecompressUdpHeader(Message &aMessage, FrameData &aFrameData, uint16_t aDatagramLength)
|
||||
{
|
||||
Error error;
|
||||
Ip6::Udp::Header udpHeader;
|
||||
int headerLen = -1;
|
||||
|
||||
headerLen = DecompressUdpHeader(udpHeader, aBuf, aBufLength);
|
||||
VerifyOrExit(headerLen >= 0);
|
||||
SuccessOrExit(error = DecompressUdpHeader(udpHeader, aFrameData));
|
||||
|
||||
// length
|
||||
if (aDatagramLength == 0)
|
||||
{
|
||||
udpHeader.SetLength(sizeof(udpHeader) + static_cast<uint16_t>(aBufLength - headerLen));
|
||||
udpHeader.SetLength(sizeof(udpHeader) + aFrameData.GetLength());
|
||||
}
|
||||
else
|
||||
{
|
||||
udpHeader.SetLength(aDatagramLength - aMessage.GetOffset());
|
||||
}
|
||||
|
||||
VerifyOrExit(aMessage.Append(udpHeader) == kErrorNone, headerLen = -1);
|
||||
SuccessOrExit(error = aMessage.Append(udpHeader));
|
||||
aMessage.MoveOffset(sizeof(udpHeader));
|
||||
|
||||
exit:
|
||||
return headerLen;
|
||||
return error;
|
||||
}
|
||||
|
||||
int Lowpan::Decompress(Message & aMessage,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
const uint8_t * aBuf,
|
||||
uint16_t aBufLength,
|
||||
uint16_t aDatagramLength)
|
||||
Error Lowpan::Decompress(Message & aMessage,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
FrameData & aFrameData,
|
||||
uint16_t aDatagramLength)
|
||||
{
|
||||
Error error = kErrorParse;
|
||||
Ip6::Header ip6Header;
|
||||
const uint8_t *cur = aBuf;
|
||||
uint16_t remaining = aBufLength;
|
||||
bool compressed;
|
||||
int rval;
|
||||
uint16_t ip6PayloadLength;
|
||||
uint16_t compressedLength = 0;
|
||||
uint16_t currentOffset = aMessage.GetOffset();
|
||||
Error error = kErrorParse;
|
||||
Ip6::Header ip6Header;
|
||||
bool compressed;
|
||||
uint16_t ip6PayloadLength;
|
||||
uint16_t currentOffset = aMessage.GetOffset();
|
||||
|
||||
VerifyOrExit(remaining >= 2);
|
||||
VerifyOrExit((rval = DecompressBaseHeader(ip6Header, compressed, aMacSource, aMacDest, cur, remaining)) >= 0);
|
||||
|
||||
cur += rval;
|
||||
remaining -= rval;
|
||||
SuccessOrExit(DecompressBaseHeader(ip6Header, compressed, aMacSource, aMacDest, aFrameData));
|
||||
|
||||
SuccessOrExit(aMessage.Append(ip6Header));
|
||||
aMessage.MoveOffset(sizeof(ip6Header));
|
||||
|
||||
while (compressed)
|
||||
{
|
||||
VerifyOrExit(remaining >= 1);
|
||||
uint8_t byte;
|
||||
|
||||
if ((cur[0] & kExtHdrDispatchMask) == kExtHdrDispatch)
|
||||
VerifyOrExit(aFrameData.GetLength() > 0);
|
||||
byte = *aFrameData.GetBytes();
|
||||
|
||||
if ((byte & kExtHdrDispatchMask) == kExtHdrDispatch)
|
||||
{
|
||||
if ((cur[0] & kExtHdrEidMask) == kExtHdrEidIp6)
|
||||
if ((byte & kExtHdrEidMask) == kExtHdrEidIp6)
|
||||
{
|
||||
compressed = false;
|
||||
|
||||
cur++;
|
||||
remaining--;
|
||||
aFrameData.SkipOver(sizeof(uint8_t));
|
||||
|
||||
VerifyOrExit((rval = Decompress(aMessage, aMacSource, aMacDest, cur, remaining, aDatagramLength)) >= 0);
|
||||
SuccessOrExit(Decompress(aMessage, aMacSource, aMacDest, aFrameData, aDatagramLength));
|
||||
}
|
||||
else
|
||||
{
|
||||
compressed = (cur[0] & kExtHdrNextHeader) != 0;
|
||||
VerifyOrExit((rval = DecompressExtensionHeader(aMessage, cur, remaining)) >= 0);
|
||||
compressed = (byte & kExtHdrNextHeader) != 0;
|
||||
SuccessOrExit(DecompressExtensionHeader(aMessage, aFrameData));
|
||||
}
|
||||
}
|
||||
else if ((cur[0] & kUdpDispatchMask) == kUdpDispatch)
|
||||
else if ((byte & kUdpDispatchMask) == kUdpDispatch)
|
||||
{
|
||||
compressed = false;
|
||||
VerifyOrExit((rval = DecompressUdpHeader(aMessage, cur, remaining, aDatagramLength)) >= 0);
|
||||
SuccessOrExit(DecompressUdpHeader(aMessage, aFrameData, aDatagramLength));
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
VerifyOrExit(remaining >= rval);
|
||||
cur += rval;
|
||||
remaining -= rval;
|
||||
}
|
||||
|
||||
compressedLength = static_cast<uint16_t>(cur - aBuf);
|
||||
|
||||
if (aDatagramLength)
|
||||
{
|
||||
ip6PayloadLength = HostSwap16(aDatagramLength - currentOffset - sizeof(Ip6::Header));
|
||||
@@ -1168,7 +1111,7 @@ int Lowpan::Decompress(Message & aMessage,
|
||||
else
|
||||
{
|
||||
ip6PayloadLength =
|
||||
HostSwap16(aMessage.GetOffset() - currentOffset - sizeof(Ip6::Header) + aBufLength - compressedLength);
|
||||
HostSwap16(aMessage.GetOffset() - currentOffset - sizeof(Ip6::Header) + aFrameData.GetLength());
|
||||
}
|
||||
|
||||
aMessage.Write(currentOffset + Ip6::Header::kPayloadLengthFieldOffset, ip6PayloadLength);
|
||||
@@ -1176,7 +1119,7 @@ int Lowpan::Decompress(Message & aMessage,
|
||||
error = kErrorNone;
|
||||
|
||||
exit:
|
||||
return (error == kErrorNone) ? static_cast<int>(compressedLength) : -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
Ip6::Ecn Lowpan::DecompressEcn(const Message &aMessage, uint16_t aOffset) const
|
||||
@@ -1229,9 +1172,21 @@ void MeshHeader::Init(uint16_t aSource, uint16_t aDestination, uint8_t aHopsLeft
|
||||
mHopsLeft = aHopsLeft;
|
||||
}
|
||||
|
||||
bool MeshHeader::IsMeshHeader(const uint8_t *aFrame, uint16_t aFrameLength)
|
||||
bool MeshHeader::IsMeshHeader(const FrameData &aFrameData)
|
||||
{
|
||||
return (aFrameLength >= kMinHeaderLength) && ((*aFrame & kDispatchMask) == kDispatch);
|
||||
return (aFrameData.GetLength() >= kMinHeaderLength) && ((*aFrameData.GetBytes() & kDispatchMask) == kDispatch);
|
||||
}
|
||||
|
||||
Error MeshHeader::ParseFrom(FrameData &aFrameData)
|
||||
{
|
||||
Error error;
|
||||
uint16_t headerLength;
|
||||
|
||||
SuccessOrExit(error = ParseFrom(aFrameData.GetBytes(), aFrameData.GetLength(), headerLength));
|
||||
aFrameData.SkipOver(headerLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error MeshHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength)
|
||||
@@ -1320,15 +1275,14 @@ uint16_t MeshHeader::WriteTo(uint8_t *aFrame) const
|
||||
return static_cast<uint16_t>(cur - aFrame);
|
||||
}
|
||||
|
||||
uint16_t MeshHeader::WriteTo(Message &aMessage, uint16_t aOffset) const
|
||||
Error MeshHeader::AppendTo(Message &aMessage) const
|
||||
{
|
||||
uint8_t frame[kDeepHopsHeaderLength];
|
||||
uint16_t headerLength;
|
||||
|
||||
headerLength = WriteTo(frame);
|
||||
aMessage.WriteBytes(aOffset, frame, headerLength);
|
||||
|
||||
return headerLength;
|
||||
return aMessage.AppendBytes(frame, headerLength);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1341,11 +1295,28 @@ void FragmentHeader::Init(uint16_t aSize, uint16_t aTag, uint16_t aOffset)
|
||||
mOffset = (aOffset & kOffsetMask);
|
||||
}
|
||||
|
||||
bool FragmentHeader::IsFragmentHeader(const FrameData &aFrameData)
|
||||
{
|
||||
return IsFragmentHeader(aFrameData.GetBytes(), aFrameData.GetLength());
|
||||
}
|
||||
|
||||
bool FragmentHeader::IsFragmentHeader(const uint8_t *aFrame, uint16_t aFrameLength)
|
||||
{
|
||||
return (aFrameLength >= kFirstFragmentHeaderSize) && ((*aFrame & kDispatchMask) == kDispatch);
|
||||
}
|
||||
|
||||
Error FragmentHeader::ParseFrom(FrameData &aFrameData)
|
||||
{
|
||||
Error error;
|
||||
uint16_t headerLength;
|
||||
|
||||
SuccessOrExit(error = ParseFrom(aFrameData.GetBytes(), aFrameData.GetLength(), headerLength));
|
||||
aFrameData.SkipOver(headerLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error FragmentHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength)
|
||||
{
|
||||
Error error = kErrorParse;
|
||||
|
||||
+90
-43
@@ -37,6 +37,7 @@
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include "common/debug.hpp"
|
||||
#include "common/frame_data.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/message.hpp"
|
||||
#include "common/non_copyable.hpp"
|
||||
@@ -244,6 +245,19 @@ public:
|
||||
return (aHeader[0] & (Lowpan::kHcDispatchMask >> 8)) == (Lowpan::kHcDispatch >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates whether or not header in a given frame is a LOWPAN_IPHC header.
|
||||
*
|
||||
* @param[in] aFrameData The frame data.
|
||||
*
|
||||
* @retval TRUE If the header matches the LOWPAN_IPHC dispatch value.
|
||||
* @retval FALSE If the header does not match the LOWPAN_IPHC dispatch value.
|
||||
*/
|
||||
static bool IsLowpanHc(const FrameData &aFrameData)
|
||||
{
|
||||
return (aFrameData.GetLength() > 0) && IsLowpanHc(aFrameData.GetBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method compresses an IPv6 header.
|
||||
*
|
||||
@@ -260,54 +274,59 @@ public:
|
||||
/**
|
||||
* This method decompresses a LOWPAN_IPHC header.
|
||||
*
|
||||
* @param[out] aMessage A reference where the IPv6 header will be placed.
|
||||
* @param[in] aMacSource The MAC source address.
|
||||
* @param[in] aMacDest The MAC destination address.
|
||||
* @param[in] aBuf A pointer to the LOWPAN_IPHC header.
|
||||
* @param[in] aBufLength The number of bytes in @p aBuf.
|
||||
* @param[in] aDatagramLength The IPv6 datagram length.
|
||||
* If the header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
|
||||
*
|
||||
* @returns The size of the compressed header in bytes.
|
||||
* @param[out] aMessage A reference where the IPv6 header will be placed.
|
||||
* @param[in] aMacSource The MAC source address.
|
||||
* @param[in] aMacDest The MAC destination address.
|
||||
* @param[in,out] aFrameData A frame data containing the LOWPAN_IPHC header.
|
||||
* @param[in] aDatagramLength The IPv6 datagram length.
|
||||
*
|
||||
* @retval kErrorNone The header was decompressed successfully. @p aMessage and @p aFrameData are updated.
|
||||
* @retval kErrorParse Failed to parse the lowpan header.
|
||||
* @retval kErrorNoBufs Could not grow @p aMessage to write the parsed IPv6 header.
|
||||
*
|
||||
*/
|
||||
int Decompress(Message & aMessage,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
const uint8_t * aBuf,
|
||||
uint16_t aBufLength,
|
||||
uint16_t aDatagramLength);
|
||||
Error Decompress(Message & aMessage,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
FrameData & aFrameData,
|
||||
uint16_t aDatagramLength);
|
||||
|
||||
/**
|
||||
* This method decompresses a LOWPAN_IPHC header.
|
||||
*
|
||||
* @param[out] aIp6Header A reference where the IPv6 header will be placed.
|
||||
* @param[out] aCompressedNextHeader A boolean reference to output whether next header is compressed or not.
|
||||
* @param[in] aMacSource The MAC source address.
|
||||
* @param[in] aMacDest The MAC destination address.
|
||||
* @param[in] aBuf A pointer to the LOWPAN_IPHC header.
|
||||
* @param[in] aBufLength The number of bytes in @p aBuf.
|
||||
* If the header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
|
||||
*
|
||||
* @returns The size of the compressed header in bytes or -1 if decompression fails.
|
||||
* @param[out] aIp6Header A reference where the IPv6 header will be placed.
|
||||
* @param[out] aCompressedNextHeader A boolean reference to output whether next header is compressed or not.
|
||||
* @param[in] aMacSource The MAC source address.
|
||||
* @param[in] aMacDest The MAC destination address.
|
||||
* @param[in,out] aFrameData A frame data containing the LOWPAN_IPHC header.
|
||||
*
|
||||
* @retval kErrorNone The header was decompressed successfully. @p aIp6Headre and @p aFrameData are updated.
|
||||
* @retval kErrorParse Failed to parse the lowpan header.
|
||||
*
|
||||
*/
|
||||
int DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
bool & aCompressedNextHeader,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
const uint8_t * aBuf,
|
||||
uint16_t aBufLength);
|
||||
Error DecompressBaseHeader(Ip6::Header & aIp6Header,
|
||||
bool & aCompressedNextHeader,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
FrameData & aFrameData);
|
||||
|
||||
/**
|
||||
* This method decompresses a LOWPAN_NHC UDP header.
|
||||
*
|
||||
* @param[out] aUdpHeader A reference where the UDP header will be placed.
|
||||
* @param[in] aBuf A pointer to the LOWPAN_NHC header.
|
||||
* @param[in] aBufLength The number of bytes in @p aBuf.
|
||||
* If the header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
|
||||
*
|
||||
* @returns The size of the compressed header in bytes or -1 if decompression fails.
|
||||
* @param[out] aUdpHeader A reference where the UDP header will be placed.
|
||||
* @param[in,out] aFrameData A frame data containing the LOWPAN_NHC header.
|
||||
*
|
||||
* @retval kErrorNone The header was decompressed successfully. @p aUdpHeader and @p aFrameData are updated.
|
||||
* @retval kErrorParse Failed to parse the lowpan header.
|
||||
*
|
||||
*/
|
||||
int DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, const uint8_t *aBuf, uint16_t aBufLength);
|
||||
Error DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, FrameData &aFrameData);
|
||||
|
||||
/**
|
||||
* This method decompresses the IPv6 ECN field in a LOWPAN_IPHC header.
|
||||
@@ -403,8 +422,8 @@ private:
|
||||
Error CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, BufferWriter &aBuf);
|
||||
Error CompressUdp(Message &aMessage, BufferWriter &aBuf);
|
||||
|
||||
int DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength);
|
||||
int DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength);
|
||||
Error DecompressExtensionHeader(Message &aMessage, FrameData &aFrameData);
|
||||
Error DecompressUdpHeader(Message &aMessage, FrameData &aFrameData, uint16_t aDatagramLength);
|
||||
Error DispatchToNextHeader(uint8_t aDispatch, uint8_t &aNextHeader);
|
||||
|
||||
static void CopyContext(const Context &aContext, Ip6::Address &aAddress);
|
||||
@@ -445,7 +464,7 @@ public:
|
||||
* @retval FALSE If the header does not match the Mesh Header dispatch value.
|
||||
*
|
||||
*/
|
||||
static bool IsMeshHeader(const uint8_t *aFrame, uint16_t aFrameLength);
|
||||
static bool IsMeshHeader(const FrameData &aFrameData);
|
||||
|
||||
/**
|
||||
* This method parses the Mesh Header from a frame @p aFrame.
|
||||
@@ -460,6 +479,19 @@ public:
|
||||
*/
|
||||
Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength);
|
||||
|
||||
/**
|
||||
* This method parses the Mesh Header from a given frame data.
|
||||
*
|
||||
* If the Mesh Header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
|
||||
*
|
||||
* @param[in,out] aFrameData The frame data to parse from.
|
||||
*
|
||||
* @retval kErrorNone Mesh Header parsed successfully. @p aFrameData is updated to skip over parsed header.
|
||||
* @retval kErrorParse Mesh Header could not be parsed.
|
||||
*
|
||||
*/
|
||||
Error ParseFrom(FrameData &aFrameData);
|
||||
|
||||
/**
|
||||
* This method parses the Mesh Header from a given message.
|
||||
*
|
||||
@@ -542,18 +574,16 @@ public:
|
||||
uint16_t WriteTo(uint8_t *aFrame) const;
|
||||
|
||||
/**
|
||||
* This method writes the Mesh Header to a message at a given offset.
|
||||
* This method appends the Mesh Header to a given message.
|
||||
*
|
||||
* @note This method expects the @p aMessage length to be already set such that there is enough space for the
|
||||
* entire Mesh Header to be written.
|
||||
*
|
||||
* @param[out] aMessage A message to write the Mesh Header into.
|
||||
* @param[in] aOffset The offset at which to write the header.
|
||||
* @param[out] aMessage A message to append the Mesh Header to.
|
||||
*
|
||||
* @returns The header length (number of bytes written).
|
||||
* @retval kErrorNone Successfully appended the Mesh Header to @p aMessage.
|
||||
* @retval kErrorNoBufs Insufficient available buffers to grow @p aMessage.
|
||||
*
|
||||
*/
|
||||
uint16_t WriteTo(Message &aMessage, uint16_t aOffset) const;
|
||||
Error AppendTo(Message &aMessage) const;
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kDispatch = 2 << 6;
|
||||
@@ -612,11 +642,13 @@ public:
|
||||
* header (dispatch byte) matches the Fragment Header dispatch value. It does not fully parse and validate the
|
||||
* Fragment Header. `ParseFrom()` method can be used to fully parse and validate the header.
|
||||
*
|
||||
* @param[in] aFrameData The frame data.
|
||||
*
|
||||
* @retval TRUE If the header matches the Fragment Header dispatch value.
|
||||
* @retval FALSE If the header does not match the Fragment Header dispatch value.
|
||||
*
|
||||
*/
|
||||
static bool IsFragmentHeader(const uint8_t *aFrame, uint16_t aFrameLength);
|
||||
static bool IsFragmentHeader(const FrameData &aFrameData);
|
||||
|
||||
/**
|
||||
* This method parses the Fragment Header from a frame @p aFrame.
|
||||
@@ -629,7 +661,20 @@ public:
|
||||
* @retval kErrorParse Fragment header could not be parsed from @p aFrame.
|
||||
*
|
||||
*/
|
||||
Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength);
|
||||
Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength); //~~~ REMOVE OR MAKE PRIVATE
|
||||
|
||||
/**
|
||||
* This method parses the Fragment Header from a given frame data.
|
||||
*
|
||||
* If the Fragment Header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
|
||||
*
|
||||
* @param[in,out] aFrameData The frame data to parse from.
|
||||
*
|
||||
* @retval kErrorNone Fragment Header parsed successfully. @p aFrameData is updated to skip over parsed header.
|
||||
* @retval kErrorParse Fragment header could not be parsed.
|
||||
*
|
||||
*/
|
||||
Error ParseFrom(FrameData &aFrameData);
|
||||
|
||||
/**
|
||||
* This method parses the Fragment Header from a message.
|
||||
@@ -694,6 +739,8 @@ private:
|
||||
static constexpr uint8_t kTagIndex = 2; // Start index of Tag field in the Fragment Header byte sequence.
|
||||
static constexpr uint8_t kOffsetIndex = 4; // Start index of Offset field in the Fragment Header byte sequence.
|
||||
|
||||
static bool IsFragmentHeader(const uint8_t *aFrame, uint16_t aFrameLength);
|
||||
|
||||
uint16_t mSize;
|
||||
uint16_t mTag;
|
||||
uint16_t mOffset;
|
||||
|
||||
@@ -1332,8 +1332,7 @@ void MeshForwarder::HandleReceivedFrame(Mac::RxFrame &aFrame)
|
||||
ThreadLinkInfo linkInfo;
|
||||
Mac::Address macDest;
|
||||
Mac::Address macSource;
|
||||
uint8_t * payload;
|
||||
uint16_t payloadLength;
|
||||
FrameData frameData;
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(mEnabled, error = kErrorInvalidState);
|
||||
@@ -1343,8 +1342,7 @@ void MeshForwarder::HandleReceivedFrame(Mac::RxFrame &aFrame)
|
||||
|
||||
linkInfo.SetFrom(aFrame);
|
||||
|
||||
payload = aFrame.GetPayload();
|
||||
payloadLength = aFrame.GetPayloadLength();
|
||||
frameData.Init(aFrame.GetPayload(), aFrame.GetPayloadLength());
|
||||
|
||||
#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
|
||||
Get<Utils::SupervisionListener>().UpdateOnReceive(macSource, linkInfo.IsLinkSecurityEnabled());
|
||||
@@ -1353,23 +1351,23 @@ void MeshForwarder::HandleReceivedFrame(Mac::RxFrame &aFrame)
|
||||
switch (aFrame.GetType())
|
||||
{
|
||||
case Mac::Frame::kFcfFrameData:
|
||||
if (Lowpan::MeshHeader::IsMeshHeader(payload, payloadLength))
|
||||
if (Lowpan::MeshHeader::IsMeshHeader(frameData))
|
||||
{
|
||||
#if OPENTHREAD_FTD
|
||||
HandleMesh(payload, payloadLength, macSource, linkInfo);
|
||||
HandleMesh(frameData, macSource, linkInfo);
|
||||
#endif
|
||||
}
|
||||
else if (Lowpan::FragmentHeader::IsFragmentHeader(payload, payloadLength))
|
||||
else if (Lowpan::FragmentHeader::IsFragmentHeader(frameData))
|
||||
{
|
||||
HandleFragment(payload, payloadLength, macSource, macDest, linkInfo);
|
||||
HandleFragment(frameData, macSource, macDest, linkInfo);
|
||||
}
|
||||
else if (payloadLength >= 1 && Lowpan::Lowpan::IsLowpanHc(payload))
|
||||
else if (Lowpan::Lowpan::IsLowpanHc(frameData))
|
||||
{
|
||||
HandleLowpanHC(payload, payloadLength, macSource, macDest, linkInfo);
|
||||
HandleLowpanHC(frameData, macSource, macDest, linkInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(payloadLength == 0, error = kErrorNotLowpanDataFrame);
|
||||
VerifyOrExit(frameData.GetLength() == 0, error = kErrorNotLowpanDataFrame);
|
||||
|
||||
LogFrame("Received empty payload frame", aFrame, kErrorNone);
|
||||
}
|
||||
@@ -1392,21 +1390,16 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleFragment(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
void MeshForwarder::HandleFragment(FrameData & aFrameData,
|
||||
const Mac::Address & aMacSource,
|
||||
const Mac::Address & aMacDest,
|
||||
const ThreadLinkInfo &aLinkInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Lowpan::FragmentHeader fragmentHeader;
|
||||
uint16_t fragmentHeaderLength;
|
||||
Message * message = nullptr;
|
||||
|
||||
// Check the fragment header
|
||||
SuccessOrExit(error = fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength));
|
||||
aFrame += fragmentHeaderLength;
|
||||
aFrameLength -= fragmentHeaderLength;
|
||||
SuccessOrExit(error = fragmentHeader.ParseFrom(aFrameData));
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
|
||||
@@ -1448,15 +1441,13 @@ void MeshForwarder::HandleFragment(const uint8_t * aFrame,
|
||||
uint16_t datagramSize = fragmentHeader.GetDatagramSize();
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
UpdateRoutes(aFrame, aFrameLength, aMacSource, aMacDest);
|
||||
UpdateRoutes(aFrameData, aMacSource, aMacDest);
|
||||
#endif
|
||||
|
||||
error = FrameToMessage(aFrame, aFrameLength, datagramSize, aMacSource, aMacDest, message);
|
||||
SuccessOrExit(error);
|
||||
SuccessOrExit(error = FrameToMessage(aFrameData, datagramSize, aMacSource, aMacDest, message));
|
||||
|
||||
VerifyOrExit(datagramSize >= message->GetLength(), error = kErrorParse);
|
||||
error = message->SetLength(datagramSize);
|
||||
SuccessOrExit(error);
|
||||
SuccessOrExit(error = message->SetLength(datagramSize));
|
||||
|
||||
message->SetDatagramTag(fragmentHeader.GetDatagramTag());
|
||||
message->SetTimestampToNow();
|
||||
@@ -1489,7 +1480,7 @@ void MeshForwarder::HandleFragment(const uint8_t * aFrame,
|
||||
if (msg.GetLength() == fragmentHeader.GetDatagramSize() &&
|
||||
msg.GetDatagramTag() == fragmentHeader.GetDatagramTag() &&
|
||||
msg.GetOffset() == fragmentHeader.GetDatagramOffset() &&
|
||||
msg.GetOffset() + aFrameLength <= fragmentHeader.GetDatagramSize() &&
|
||||
msg.GetOffset() + aFrameData.GetLength() <= fragmentHeader.GetDatagramSize() &&
|
||||
msg.IsLinkSecurityEnabled() == aLinkInfo.IsLinkSecurityEnabled())
|
||||
{
|
||||
message = &msg;
|
||||
@@ -1510,8 +1501,8 @@ void MeshForwarder::HandleFragment(const uint8_t * aFrame,
|
||||
|
||||
VerifyOrExit(message != nullptr, error = kErrorDrop);
|
||||
|
||||
message->WriteBytes(message->GetOffset(), aFrame, aFrameLength);
|
||||
message->MoveOffset(aFrameLength);
|
||||
message->WriteData(message->GetOffset(), aFrameData);
|
||||
message->MoveOffset(aFrameData.GetLength());
|
||||
message->AddRss(aLinkInfo.GetRss());
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
message->AddLqi(aLinkInfo.GetLqi());
|
||||
@@ -1531,7 +1522,7 @@ exit:
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFragmentFrameDrop(error, aFrameLength, aMacSource, aMacDest, fragmentHeader,
|
||||
LogFragmentFrameDrop(error, aFrameData.GetLength(), aMacSource, aMacDest, fragmentHeader,
|
||||
aLinkInfo.IsLinkSecurityEnabled());
|
||||
FreeMessage(message);
|
||||
}
|
||||
@@ -1590,40 +1581,31 @@ bool MeshForwarder::UpdateReassemblyList(void)
|
||||
return mReassemblyList.GetHead() != nullptr;
|
||||
}
|
||||
|
||||
Error MeshForwarder::FrameToMessage(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
Error MeshForwarder::FrameToMessage(const FrameData & aFrameData,
|
||||
uint16_t aDatagramSize,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
Message *& aMessage)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
int headerLength;
|
||||
Error error = kErrorNone;
|
||||
FrameData frameData = aFrameData;
|
||||
Message::Priority priority;
|
||||
|
||||
error = GetFramePriority(aFrame, aFrameLength, aMacSource, aMacDest, priority);
|
||||
SuccessOrExit(error);
|
||||
SuccessOrExit(error = GetFramePriority(frameData, aMacSource, aMacDest, priority));
|
||||
|
||||
aMessage = Get<MessagePool>().Allocate(Message::kTypeIp6, /* aReserveHeader */ 0, Message::Settings(priority));
|
||||
VerifyOrExit(aMessage, error = kErrorNoBufs);
|
||||
|
||||
headerLength =
|
||||
Get<Lowpan::Lowpan>().Decompress(*aMessage, aMacSource, aMacDest, aFrame, aFrameLength, aDatagramSize);
|
||||
VerifyOrExit(headerLength > 0, error = kErrorParse);
|
||||
SuccessOrExit(error = Get<Lowpan::Lowpan>().Decompress(*aMessage, aMacSource, aMacDest, frameData, aDatagramSize));
|
||||
|
||||
aFrame += headerLength;
|
||||
aFrameLength -= static_cast<uint16_t>(headerLength);
|
||||
|
||||
SuccessOrExit(error = aMessage->SetLength(aMessage->GetLength() + aFrameLength));
|
||||
aMessage->WriteBytes(aMessage->GetOffset(), aFrame, aFrameLength);
|
||||
aMessage->MoveOffset(aFrameLength);
|
||||
SuccessOrExit(error = aMessage->AppendData(frameData));
|
||||
aMessage->MoveOffset(frameData.GetLength());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleLowpanHC(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
void MeshForwarder::HandleLowpanHC(const FrameData & aFrameData,
|
||||
const Mac::Address & aMacSource,
|
||||
const Mac::Address & aMacDest,
|
||||
const ThreadLinkInfo &aLinkInfo)
|
||||
@@ -1632,10 +1614,10 @@ void MeshForwarder::HandleLowpanHC(const uint8_t * aFrame,
|
||||
Message *message = nullptr;
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
UpdateRoutes(aFrame, aFrameLength, aMacSource, aMacDest);
|
||||
UpdateRoutes(aFrameData, aMacSource, aMacDest);
|
||||
#endif
|
||||
|
||||
SuccessOrExit(error = FrameToMessage(aFrame, aFrameLength, 0, aMacSource, aMacDest, message));
|
||||
SuccessOrExit(error = FrameToMessage(aFrameData, 0, aMacSource, aMacDest, message));
|
||||
|
||||
message->SetLinkInfo(aLinkInfo);
|
||||
|
||||
@@ -1653,7 +1635,7 @@ exit:
|
||||
}
|
||||
else
|
||||
{
|
||||
LogLowpanHcFrameDrop(error, aFrameLength, aMacSource, aMacDest, aLinkInfo.IsLinkSecurityEnabled());
|
||||
LogLowpanHcFrameDrop(error, aFrameData.GetLength(), aMacSource, aMacDest, aLinkInfo.IsLinkSecurityEnabled());
|
||||
FreeMessage(message);
|
||||
}
|
||||
}
|
||||
@@ -1676,8 +1658,7 @@ Error MeshForwarder::HandleDatagram(Message &aMessage, const ThreadLinkInfo &aLi
|
||||
return Get<Ip6::Ip6>().HandleDatagram(aMessage, &netif, &aLinkInfo, false);
|
||||
}
|
||||
|
||||
Error MeshForwarder::GetFramePriority(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
Error MeshForwarder::GetFramePriority(const FrameData & aFrameData,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
Message::Priority & aPriority)
|
||||
@@ -1685,7 +1666,7 @@ Error MeshForwarder::GetFramePriority(const uint8_t * aFrame,
|
||||
Error error = kErrorNone;
|
||||
Ip6::Headers headers;
|
||||
|
||||
SuccessOrExit(error = headers.DecompressFrom(aFrame, aFrameLength, aMacSource, aMacDest, GetInstance()));
|
||||
SuccessOrExit(error = headers.DecompressFrom(aFrameData, aMacSource, aMacDest, GetInstance()));
|
||||
|
||||
aPriority = Ip6::Ip6::DscpToPriority(headers.GetIp6Header().GetDscp());
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/clearable.hpp"
|
||||
#include "common/frame_data.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/log.hpp"
|
||||
#include "common/non_copyable.hpp"
|
||||
@@ -425,16 +426,11 @@ private:
|
||||
void SendIcmpErrorIfDstUnreach(const Message & aMessage,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest);
|
||||
Error CheckReachability(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
Error CheckReachability(const FrameData & aFrameData,
|
||||
const Mac::Address &aMeshSource,
|
||||
const Mac::Address &aMeshDest);
|
||||
void UpdateRoutes(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
const Mac::Address &aMeshSource,
|
||||
const Mac::Address &aMeshDest);
|
||||
Error FrameToMessage(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
void UpdateRoutes(const FrameData &aFrameData, const Mac::Address &aMeshSource, const Mac::Address &aMeshDest);
|
||||
Error FrameToMessage(const FrameData & aFrameData,
|
||||
uint16_t aDatagramSize,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
@@ -442,17 +438,12 @@ private:
|
||||
void GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
|
||||
void GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
|
||||
Message *PrepareNextDirectTransmission(void);
|
||||
void HandleMesh(uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
const Mac::Address & aMacSource,
|
||||
const ThreadLinkInfo &aLinkInfo);
|
||||
void HandleFragment(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
void HandleMesh(FrameData &aFrameData, const Mac::Address &aMacSource, const ThreadLinkInfo &aLinkInfo);
|
||||
void HandleFragment(FrameData & aFrameData,
|
||||
const Mac::Address & aMacSource,
|
||||
const Mac::Address & aMacDest,
|
||||
const ThreadLinkInfo &aLinkInfo);
|
||||
void HandleLowpanHC(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
void HandleLowpanHC(const FrameData & aFrameData,
|
||||
const Mac::Address & aMacSource,
|
||||
const Mac::Address & aMacDest,
|
||||
const ThreadLinkInfo &aLinkInfo);
|
||||
@@ -505,16 +496,14 @@ private:
|
||||
static void ScheduleTransmissionTask(Tasklet &aTasklet);
|
||||
void ScheduleTransmissionTask(void);
|
||||
|
||||
Error GetFramePriority(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
Error GetFramePriority(const FrameData & aFrameData,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest,
|
||||
Message::Priority & aPriority);
|
||||
Error GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,
|
||||
uint16_t aSrcRloc16,
|
||||
Message::Priority & aPriority);
|
||||
void GetForwardFramePriority(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
void GetForwardFramePriority(const FrameData & aFrameData,
|
||||
const Mac::Address &aMeshSource,
|
||||
const Mac::Address &aMeshDest,
|
||||
Message::Priority & aPriority);
|
||||
|
||||
@@ -666,15 +666,14 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error MeshForwarder::CheckReachability(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
Error MeshForwarder::CheckReachability(const FrameData & aFrameData,
|
||||
const Mac::Address &aMeshSource,
|
||||
const Mac::Address &aMeshDest)
|
||||
{
|
||||
Error error;
|
||||
Ip6::Headers ip6Headers;
|
||||
|
||||
error = ip6Headers.DecompressFrom(aFrame, aFrameLength, aMeshSource, aMeshDest, GetInstance());
|
||||
error = ip6Headers.DecompressFrom(aFrameData, aMeshSource, aMeshDest, GetInstance());
|
||||
|
||||
if (error == kErrorNotFound)
|
||||
{
|
||||
@@ -704,41 +703,34 @@ void MeshForwarder::SendDestinationUnreachable(uint16_t aMeshSource, const Ip6::
|
||||
Ip6::Icmp::Header::kCodeDstUnreachNoRoute, messageInfo, aIp6Headers));
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleMesh(uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
const Mac::Address & aMacSource,
|
||||
const ThreadLinkInfo &aLinkInfo)
|
||||
void MeshForwarder::HandleMesh(FrameData &aFrameData, const Mac::Address &aMacSource, const ThreadLinkInfo &aLinkInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Message * message = nullptr;
|
||||
Mac::Address meshDest;
|
||||
Mac::Address meshSource;
|
||||
Lowpan::MeshHeader meshHeader;
|
||||
uint16_t headerLength;
|
||||
|
||||
// Security Check: only process Mesh Header frames that had security enabled.
|
||||
VerifyOrExit(aLinkInfo.IsLinkSecurityEnabled(), error = kErrorSecurity);
|
||||
|
||||
SuccessOrExit(error = meshHeader.ParseFrom(aFrame, aFrameLength, headerLength));
|
||||
SuccessOrExit(error = meshHeader.ParseFrom(aFrameData));
|
||||
|
||||
meshSource.SetShort(meshHeader.GetSource());
|
||||
meshDest.SetShort(meshHeader.GetDestination());
|
||||
|
||||
aFrame += headerLength;
|
||||
aFrameLength -= headerLength;
|
||||
|
||||
UpdateRoutes(aFrame, aFrameLength, meshSource, meshDest);
|
||||
UpdateRoutes(aFrameData, meshSource, meshDest);
|
||||
|
||||
if (meshDest.GetShort() == Get<Mac::Mac>().GetShortAddress() ||
|
||||
Get<Mle::MleRouter>().IsMinimalChild(meshDest.GetShort()))
|
||||
{
|
||||
if (Lowpan::FragmentHeader::IsFragmentHeader(aFrame, aFrameLength))
|
||||
if (Lowpan::FragmentHeader::IsFragmentHeader(aFrameData))
|
||||
{
|
||||
HandleFragment(aFrame, aFrameLength, meshSource, meshDest, aLinkInfo);
|
||||
HandleFragment(aFrameData, meshSource, meshDest, aLinkInfo);
|
||||
}
|
||||
else if (Lowpan::Lowpan::IsLowpanHc(aFrame))
|
||||
else if (Lowpan::Lowpan::IsLowpanHc(aFrameData))
|
||||
{
|
||||
HandleLowpanHC(aFrame, aFrameLength, meshSource, meshDest, aLinkInfo);
|
||||
HandleLowpanHC(aFrameData, meshSource, meshDest, aLinkInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -748,22 +740,21 @@ void MeshForwarder::HandleMesh(uint8_t * aFrame,
|
||||
else if (meshHeader.GetHopsLeft() > 0)
|
||||
{
|
||||
Message::Priority priority = Message::kPriorityNormal;
|
||||
uint16_t offset = 0;
|
||||
|
||||
Get<Mle::MleRouter>().ResolveRoutingLoops(aMacSource.GetShort(), meshDest.GetShort());
|
||||
|
||||
SuccessOrExit(error = CheckReachability(aFrame, aFrameLength, meshSource, meshDest));
|
||||
SuccessOrExit(error = CheckReachability(aFrameData, meshSource, meshDest));
|
||||
|
||||
meshHeader.DecrementHopsLeft();
|
||||
|
||||
GetForwardFramePriority(aFrame, aFrameLength, meshSource, meshDest, priority);
|
||||
GetForwardFramePriority(aFrameData, meshSource, meshDest, priority);
|
||||
message =
|
||||
Get<MessagePool>().Allocate(Message::kType6lowpan, /* aReserveHeader */ 0, Message::Settings(priority));
|
||||
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error = message->SetLength(meshHeader.GetHeaderLength() + aFrameLength));
|
||||
offset += meshHeader.WriteTo(*message, offset);
|
||||
message->WriteBytes(offset, aFrame, aFrameLength);
|
||||
SuccessOrExit(error = meshHeader.AppendTo(*message));
|
||||
SuccessOrExit(error = message->AppendData(aFrameData));
|
||||
|
||||
message->SetLinkInfo(aLinkInfo);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
@@ -789,14 +780,13 @@ exit:
|
||||
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
LogInfo("Dropping rx mesh frame, error:%s, len:%d, src:%s, sec:%s", ErrorToString(error), aFrameLength,
|
||||
aMacSource.ToString().AsCString(), ToYesNo(aLinkInfo.IsLinkSecurityEnabled()));
|
||||
LogInfo("Dropping rx mesh frame, error:%s, len:%d, src:%s, sec:%s", ErrorToString(error),
|
||||
aFrameData.GetLength(), aMacSource.ToString().AsCString(), ToYesNo(aLinkInfo.IsLinkSecurityEnabled()));
|
||||
FreeMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshForwarder::UpdateRoutes(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
void MeshForwarder::UpdateRoutes(const FrameData & aFrameData,
|
||||
const Mac::Address &aMeshSource,
|
||||
const Mac::Address &aMeshDest)
|
||||
{
|
||||
@@ -805,7 +795,7 @@ void MeshForwarder::UpdateRoutes(const uint8_t * aFrame,
|
||||
|
||||
VerifyOrExit(!aMeshDest.IsBroadcast() && aMeshSource.IsShort());
|
||||
|
||||
SuccessOrExit(ip6Headers.DecompressFrom(aFrame, aFrameLength, aMeshSource, aMeshDest, GetInstance()));
|
||||
SuccessOrExit(ip6Headers.DecompressFrom(aFrameData, aMeshSource, aMeshDest, GetInstance()));
|
||||
|
||||
if (!ip6Headers.GetSourceAddress().GetIid().IsLocator() &&
|
||||
Get<NetworkData::Leader>().IsOnMesh(ip6Headers.GetSourceAddress()))
|
||||
@@ -944,22 +934,19 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MeshForwarder::GetForwardFramePriority(const uint8_t * aFrame,
|
||||
uint16_t aFrameLength,
|
||||
void MeshForwarder::GetForwardFramePriority(const FrameData & aFrameData,
|
||||
const Mac::Address &aMeshSource,
|
||||
const Mac::Address &aMeshDest,
|
||||
Message::Priority & aPriority)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
FrameData frameData = aFrameData;
|
||||
bool isFragment = false;
|
||||
Lowpan::FragmentHeader fragmentHeader;
|
||||
uint16_t fragmentHeaderLength;
|
||||
|
||||
if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone)
|
||||
if (fragmentHeader.ParseFrom(frameData) == kErrorNone)
|
||||
{
|
||||
isFragment = true;
|
||||
aFrame += fragmentHeaderLength;
|
||||
aFrameLength -= fragmentHeaderLength;
|
||||
|
||||
if (fragmentHeader.GetDatagramOffset() > 0)
|
||||
{
|
||||
@@ -969,20 +956,18 @@ void MeshForwarder::GetForwardFramePriority(const uint8_t * aFrame,
|
||||
}
|
||||
|
||||
// Get priority from IPv6 header or UDP destination port directly
|
||||
error = GetFramePriority(aFrame, aFrameLength, aMeshSource, aMeshDest, aPriority);
|
||||
error = GetFramePriority(frameData, aMeshSource, aMeshDest, aPriority);
|
||||
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
LogNote("Failed to get forwarded frame priority, error:%s, len:%d, src:%d, dst:%s", ErrorToString(error),
|
||||
aFrameLength, aMeshSource.ToString().AsCString(), aMeshDest.ToString().AsCString());
|
||||
frameData.GetLength(), aMeshSource.ToString().AsCString(), aMeshDest.ToString().AsCString());
|
||||
}
|
||||
else if (isFragment)
|
||||
{
|
||||
UpdateFragmentPriority(fragmentHeader, aFrameLength, aMeshSource.GetShort(), aPriority);
|
||||
UpdateFragmentPriority(fragmentHeader, frameData.GetLength(), aMeshSource.GetShort(), aPriority);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
|
||||
+82
-44
@@ -145,12 +145,14 @@ static void Init(void)
|
||||
*/
|
||||
static void Test(TestIphcVector &aVector, bool aCompress, bool aDecompress)
|
||||
{
|
||||
Message *message = nullptr;
|
||||
uint8_t result[512];
|
||||
uint8_t iphc[512];
|
||||
uint8_t ip6[512];
|
||||
uint16_t iphcLength;
|
||||
uint16_t ip6Length;
|
||||
Message * message = nullptr;
|
||||
uint8_t result[512];
|
||||
uint8_t iphc[512];
|
||||
uint8_t ip6[512];
|
||||
uint16_t iphcLength;
|
||||
uint16_t ip6Length;
|
||||
FrameData frameData;
|
||||
Error error;
|
||||
|
||||
aVector.GetCompressedStream(iphc, iphcLength);
|
||||
aVector.GetUncompressedStream(ip6, ip6Length);
|
||||
@@ -223,28 +225,29 @@ static void Test(TestIphcVector &aVector, bool aCompress, bool aDecompress)
|
||||
{
|
||||
VerifyOrQuit((message = sInstance->Get<MessagePool>().Allocate(Message::kTypeIp6)) != nullptr);
|
||||
|
||||
int decompressedBytes =
|
||||
sLowpan->Decompress(*message, aVector.mMacSource, aVector.mMacDestination, iphc, iphcLength, 0);
|
||||
frameData.Init(iphc, iphcLength);
|
||||
|
||||
error = sLowpan->Decompress(*message, aVector.mMacSource, aVector.mMacDestination, frameData, 0);
|
||||
|
||||
message->ReadBytes(0, result, message->GetLength());
|
||||
|
||||
if (aVector.mError == kErrorNone)
|
||||
{
|
||||
SuccessOrQuit(error, "Lowpan::Decompress failed");
|
||||
|
||||
// Append payload to the IPv6 Packet.
|
||||
memcpy(result + message->GetLength(), iphc + decompressedBytes,
|
||||
iphcLength - static_cast<uint16_t>(decompressedBytes));
|
||||
memcpy(result + message->GetLength(), frameData.GetBytes(), frameData.GetLength());
|
||||
|
||||
DumpBuffer("Resulted IPv6 uncompressed packet", result,
|
||||
message->GetLength() + iphcLength - static_cast<uint16_t>(decompressedBytes));
|
||||
DumpBuffer("Resulted IPv6 uncompressed packet", result, message->GetLength() + frameData.GetLength());
|
||||
|
||||
VerifyOrQuit(decompressedBytes == aVector.mIphcHeader.mLength, "Lowpan::Decompress failed");
|
||||
VerifyOrQuit((frameData.GetBytes() - iphc) == aVector.mIphcHeader.mLength, "Lowpan::Decompress failed");
|
||||
VerifyOrQuit(message->GetOffset() == aVector.mPayloadOffset, "Lowpan::Decompress failed");
|
||||
VerifyOrQuit(message->GetOffset() == message->GetLength(), "Lowpan::Decompress failed");
|
||||
VerifyOrQuit(memcmp(ip6, result, ip6Length) == 0, "Lowpan::Decompress failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrQuit(decompressedBytes < 0, "Lowpan::Decompress failed");
|
||||
VerifyOrQuit(error == kErrorParse, "Lowpan::Decompress failed");
|
||||
}
|
||||
|
||||
message->Free();
|
||||
@@ -1864,7 +1867,7 @@ void TestLowpanMeshHeader(void)
|
||||
|
||||
uint8_t frame[kMaxFrameSize];
|
||||
uint16_t length;
|
||||
uint16_t headerLength;
|
||||
FrameData frameData;
|
||||
Lowpan::MeshHeader meshHeader;
|
||||
|
||||
meshHeader.Init(kSourceAddr, kDestAddr, 1);
|
||||
@@ -1878,14 +1881,17 @@ void TestLowpanMeshHeader(void)
|
||||
VerifyOrQuit(memcmp(frame, kMeshHeader1, length) == 0, "MeshHeader::WriteTo() failed");
|
||||
|
||||
memset(&meshHeader, 0, sizeof(meshHeader));
|
||||
VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frame, length));
|
||||
SuccessOrQuit(meshHeader.ParseFrom(frame, length, headerLength));
|
||||
VerifyOrQuit(headerLength == length, "MeshHeader::ParseFrom() returned length is incorrect");
|
||||
frameData.Init(frame, length);
|
||||
VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frameData));
|
||||
SuccessOrQuit(meshHeader.ParseFrom(frameData));
|
||||
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(meshHeader.GetSource() == kSourceAddr, "failed after ParseFrom()");
|
||||
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
|
||||
VerifyOrQuit(meshHeader.GetHopsLeft() == 1, "failed after ParseFrom()");
|
||||
|
||||
VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
|
||||
frameData.Init(frame, length - 1);
|
||||
VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
|
||||
"MeshHeader::ParseFrom() did not fail with incorrect length");
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -1901,27 +1907,34 @@ void TestLowpanMeshHeader(void)
|
||||
VerifyOrQuit(memcmp(frame, kMeshHeader2, length) == 0, "MeshHeader::WriteTo() failed");
|
||||
|
||||
memset(&meshHeader, 0, sizeof(meshHeader));
|
||||
VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frame, length));
|
||||
SuccessOrQuit(meshHeader.ParseFrom(frame, length, headerLength));
|
||||
VerifyOrQuit(headerLength == length, "MeshHeader::ParseFrom() returned length is incorrect");
|
||||
frameData.Init(frame, length);
|
||||
VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frameData));
|
||||
SuccessOrQuit(meshHeader.ParseFrom(frameData));
|
||||
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(meshHeader.GetSource() == kSourceAddr, "failed after ParseFrom()");
|
||||
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
|
||||
VerifyOrQuit(meshHeader.GetHopsLeft() == 0x20, "failed after ParseFrom()");
|
||||
|
||||
VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
|
||||
frameData.Init(frame, length - 1);
|
||||
VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
|
||||
"MeshHeader::ParseFrom() did not fail with incorrect length");
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
SuccessOrQuit(meshHeader.ParseFrom(kMeshHeader3, sizeof(kMeshHeader3), headerLength));
|
||||
VerifyOrQuit(headerLength == sizeof(kMeshHeader3), "MeshHeader::ParseFrom() returned length is incorrect");
|
||||
length = sizeof(kMeshHeader3);
|
||||
frameData.Init(kMeshHeader3, sizeof(kMeshHeader3));
|
||||
SuccessOrQuit(meshHeader.ParseFrom(frameData));
|
||||
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(frameData.GetBytes() - kMeshHeader3 == length, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(meshHeader.GetSource() == kSourceAddr, "failed after ParseFrom()");
|
||||
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
|
||||
VerifyOrQuit(meshHeader.GetHopsLeft() == 1, "failed after ParseFrom()");
|
||||
|
||||
VerifyOrQuit(meshHeader.WriteTo(frame) == sizeof(kMeshHeader1));
|
||||
|
||||
VerifyOrQuit(meshHeader.ParseFrom(kMeshHeader3, sizeof(kMeshHeader3) - 1, headerLength) == kErrorParse,
|
||||
frameData.Init(kMeshHeader3, sizeof(kMeshHeader3) - 1);
|
||||
VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
|
||||
"MeshHeader::ParseFrom() did not fail with incorrect length");
|
||||
}
|
||||
|
||||
@@ -1945,7 +1958,7 @@ void TestLowpanFragmentHeader(void)
|
||||
|
||||
uint8_t frame[kMaxFrameSize];
|
||||
uint16_t length;
|
||||
uint16_t headerLength;
|
||||
FrameData frameData;
|
||||
Lowpan::FragmentHeader fragHeader;
|
||||
|
||||
fragHeader.InitFirstFragment(kSize, kTag);
|
||||
@@ -1960,15 +1973,21 @@ void TestLowpanFragmentHeader(void)
|
||||
VerifyOrQuit(memcmp(frame, kFragHeader1, length) == 0, "FragmentHeader::WriteTo() failed");
|
||||
|
||||
memset(&fragHeader, 0, sizeof(fragHeader));
|
||||
VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frame, length));
|
||||
SuccessOrQuit(fragHeader.ParseFrom(frame, length, headerLength));
|
||||
VerifyOrQuit(headerLength == length, "FragmentHeader::ParseFrom() returned length is incorrect");
|
||||
|
||||
frameData.Init(frame, length);
|
||||
VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frameData));
|
||||
SuccessOrQuit(fragHeader.ParseFrom(frameData));
|
||||
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after ParseFrom()");
|
||||
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after ParseFrom()");
|
||||
VerifyOrQuit(fragHeader.GetDatagramOffset() == 0, "failed after ParseFrom()");
|
||||
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
|
||||
frameData.Init(frame, length - 1);
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frameData) == kErrorParse,
|
||||
"FragmentHeader::ParseFrom() did not fail with incorrect length");
|
||||
VerifyOrQuit(frameData.GetLength() == length - 1);
|
||||
VerifyOrQuit(frameData.GetBytes() == frame);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
@@ -1990,51 +2009,70 @@ void TestLowpanFragmentHeader(void)
|
||||
VerifyOrQuit(memcmp(frame, kFragHeader2, length) == 0, "FragmentHeader::WriteTo() failed");
|
||||
|
||||
memset(&fragHeader, 0, sizeof(fragHeader));
|
||||
VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frame, length));
|
||||
SuccessOrQuit(fragHeader.ParseFrom(frame, length, headerLength));
|
||||
VerifyOrQuit(headerLength == length, "FragmentHeader::ParseFrom() returned length is incorrect");
|
||||
frameData.Init(frame, length);
|
||||
VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frameData));
|
||||
SuccessOrQuit(fragHeader.ParseFrom(frameData));
|
||||
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after ParseFrom()");
|
||||
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after ParseFrom()");
|
||||
VerifyOrQuit(fragHeader.GetDatagramOffset() == kOffset, "failed after ParseFrom()");
|
||||
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
|
||||
frameData.Init(frame, length - 1);
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frameData) == kErrorParse,
|
||||
"FragmentHeader::ParseFrom() did not fail with incorrect length");
|
||||
VerifyOrQuit(frameData.GetLength() == length - 1);
|
||||
VerifyOrQuit(frameData.GetBytes() == frame);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
length = sizeof(kFragHeader3);
|
||||
memcpy(frame, kFragHeader3, length);
|
||||
SuccessOrQuit(fragHeader.ParseFrom(frame, length, headerLength));
|
||||
VerifyOrQuit(headerLength == length, "FragmentHeader::ParseFrom() returned length is incorrect");
|
||||
frameData.Init(frame, length);
|
||||
SuccessOrQuit(fragHeader.ParseFrom(frameData));
|
||||
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
|
||||
VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after ParseFrom()");
|
||||
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after ParseFrom()");
|
||||
VerifyOrQuit(fragHeader.GetDatagramOffset() == 0, "failed after ParseFrom()");
|
||||
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
|
||||
frameData.Init(frame, length - 1);
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frameData) == kErrorParse,
|
||||
"FragmentHeader::ParseFrom() did not fail with incorrect length");
|
||||
VerifyOrQuit(frameData.GetLength() == length - 1);
|
||||
VerifyOrQuit(frameData.GetBytes() == frame);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
length = sizeof(kInvalidFragHeader1);
|
||||
memcpy(frame, kInvalidFragHeader1, length);
|
||||
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
|
||||
frameData.Init(frame, length);
|
||||
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frameData),
|
||||
"IsFragmentHeader() did not detect invalid header");
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frameData) != kErrorNone,
|
||||
"FragmentHeader::ParseFrom() did not fail with invalid header");
|
||||
VerifyOrQuit(frameData.GetLength() == length);
|
||||
VerifyOrQuit(frameData.GetBytes() == frame);
|
||||
|
||||
length = sizeof(kInvalidFragHeader2);
|
||||
memcpy(frame, kInvalidFragHeader2, length);
|
||||
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
|
||||
frameData.Init(frame, length);
|
||||
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frameData),
|
||||
"IsFragmentHeader() did not detect invalid header");
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frameData) != kErrorNone,
|
||||
"FragmentHeader::ParseFrom() did not fail with invalid header");
|
||||
VerifyOrQuit(frameData.GetLength() == length);
|
||||
VerifyOrQuit(frameData.GetBytes() == frame);
|
||||
|
||||
length = sizeof(kInvalidFragHeader3);
|
||||
memcpy(frame, kInvalidFragHeader3, length);
|
||||
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
|
||||
frameData.Init(frame, length);
|
||||
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frameData),
|
||||
"IsFragmentHeader() did not detect invalid header");
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
|
||||
VerifyOrQuit(fragHeader.ParseFrom(frameData) != kErrorNone,
|
||||
"FragmentHeader::ParseFrom() did not fail with invalid header");
|
||||
VerifyOrQuit(frameData.GetLength() == length);
|
||||
VerifyOrQuit(frameData.GetBytes() == frame);
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
Reference in New Issue
Block a user