Skip to content

Commit

Permalink
[Group] Add group ID retrieval (#9765)
Browse files Browse the repository at this point in the history
* Add group ID retrieval

* Fix test

* restyle fix

* Fix comments
  • Loading branch information
jepenven-silabs authored Sep 21, 2021
1 parent ef86d99 commit cabc2f8
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 5 deletions.
3 changes: 1 addition & 2 deletions src/app/util/basic-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

#include <stdint.h>

// Pull in NodeId
#include <lib/core/GroupId.h>
#include <lib/core/NodeId.h>

// Pull in VendorId
Expand All @@ -44,7 +44,6 @@ typedef uint64_t EventNumber;
typedef uint64_t FabricId;
typedef uint8_t FabricIndex;
typedef uint32_t FieldId;
typedef uint16_t GroupId;
typedef uint16_t ListIndex;
typedef uint32_t TransactionId;
typedef uint32_t StatusCode;
Expand Down
1 change: 1 addition & 0 deletions src/lib/core/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ static_library("core") {
"CHIPTLVUpdater.cpp",
"CHIPTLVUtilities.cpp",
"CHIPTLVWriter.cpp",
"GroupId.h",
"NodeId.h",
"PeerId.h",
]
Expand Down
57 changes: 57 additions & 0 deletions src/lib/core/GroupId.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <cstdint>

namespace chip {

using GroupId = uint16_t;

constexpr GroupId kUndefinedGroupId = 0;

constexpr GroupId kMinUniversalGroupId = 0x8000;
constexpr GroupId kMaxUniversalGroupId = 0xFFFF;

constexpr GroupId kMinFabricGroupId = 0x0001;
constexpr GroupId kMaxFabricGroupId = 0x7FFF;

constexpr GroupId kAllNodes = 0xFFFF;
constexpr GroupId kAllNonSleepy = 0xFFFE;
constexpr GroupId kAllProxies = 0xFFFD;

constexpr GroupId kMinUniversalGroupIdReserved = 0x8000;
constexpr GroupId kMaxUniversalGroupIdReserved = 0xFFFC;

constexpr bool IsOperationalGroupId(GroupId aGroupId)
{
return (aGroupId != kUndefinedGroupId) &&
((aGroupId < kMinUniversalGroupIdReserved) || (aGroupId > kMaxUniversalGroupIdReserved));
}

constexpr bool IsFabricGroupId(GroupId aGroupId)
{
return (aGroupId <= kMaxFabricGroupId) && (aGroupId >= kMinFabricGroupId);
}

constexpr bool IsUniversalGroupId(GroupId aGroupId)
{
return (aGroupId >= kMinUniversalGroupId);
}

} // namespace chip
35 changes: 32 additions & 3 deletions src/transport/raw/MessageHeader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ constexpr size_t kEncryptedHeaderSizeBytes = 6;
/// size of a serialized node id inside a header
constexpr size_t kNodeIdSizeBytes = 8;

/// size of a serialized group id inside a header
constexpr size_t kGroupIdSizeBytes = 2;

/// size of a serialized vendor id inside a header
constexpr size_t kVendorIdSizeBytes = 2;

Expand Down Expand Up @@ -102,6 +105,10 @@ uint16_t PacketHeader::EncodeSizeBytes() const
{
size += kNodeIdSizeBytes;
}
else if (mDestinationGroupId.HasValue())
{
size += kGroupIdSizeBytes;
}

static_assert(kFixedUnencryptedHeaderSizeBytes + kNodeIdSizeBytes + kNodeIdSizeBytes <= UINT16_MAX,
"Header size does not fit in uint16_t");
Expand Down Expand Up @@ -173,17 +180,32 @@ CHIP_ERROR PacketHeader::Decode(const uint8_t * const data, uint16_t size, uint1
{
mSourceNodeId.ClearValue();
}

if (mFlags.Has(Header::FlagValues::kDestinationNodeIdPresent))
if (mFlags.HasAll(Header::FlagValues::kDestinationNodeIdPresent, Header::FlagValues::kDestinationGroupIdPresent))
{
// Reserved.
err = CHIP_ERROR_INTERNAL;
SuccessOrExit(err);
}
else if (mFlags.Has(Header::FlagValues::kDestinationNodeIdPresent))
{
uint64_t destinationNodeId;
err = reader.Read64(&destinationNodeId).StatusCode();
SuccessOrExit(err);
mDestinationNodeId.SetValue(destinationNodeId);
mDestinationGroupId.ClearValue();
}
else if (mFlags.Has(Header::FlagValues::kDestinationGroupIdPresent))
{
uint16_t destinationGroupId;
err = reader.Read16(&destinationGroupId).StatusCode();
SuccessOrExit(err);
mDestinationGroupId.SetValue(destinationGroupId);
mDestinationNodeId.ClearValue();
}
else
{
mDestinationNodeId.ClearValue();
mDestinationGroupId.ClearValue();
}

octets_read = static_cast<uint16_t>(reader.OctetsRead());
Expand Down Expand Up @@ -266,10 +288,12 @@ CHIP_ERROR PayloadHeader::DecodeAndConsume(const System::PacketBufferHandle & bu
CHIP_ERROR PacketHeader::Encode(uint8_t * data, uint16_t size, uint16_t * encode_size) const
{
VerifyOrReturnError(size >= EncodeSizeBytes(), CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(!(mDestinationNodeId.HasValue() && mDestinationGroupId.HasValue()), CHIP_ERROR_INTERNAL);

Header::Flags encodeFlags = mFlags;
encodeFlags.Set(Header::FlagValues::kSourceNodeIdPresent, mSourceNodeId.HasValue())
.Set(Header::FlagValues::kDestinationNodeIdPresent, mDestinationNodeId.HasValue());
.Set(Header::FlagValues::kDestinationNodeIdPresent, mDestinationNodeId.HasValue())
.Set(Header::FlagValues::kDestinationGroupIdPresent, mDestinationGroupId.HasValue());

uint16_t header = (kMsgHeaderVersion << kVersionShift) | encodeFlags.Raw();
header |= (static_cast<uint16_t>(static_cast<uint16_t>(mSessionType) << kSessionTypeShift) & kSessionTypeMask);
Expand All @@ -287,6 +311,11 @@ CHIP_ERROR PacketHeader::Encode(uint8_t * data, uint16_t size, uint16_t * encode
LittleEndian::Write64(p, mDestinationNodeId.Value());
}

if (mDestinationGroupId.HasValue())
{
LittleEndian::Write16(p, mDestinationGroupId.Value());
}

// Written data size provided to caller on success
VerifyOrReturnError(p - data == EncodeSizeBytes(), CHIP_ERROR_INTERNAL);
*encode_size = static_cast<uint16_t>(p - data);
Expand Down
30 changes: 30 additions & 0 deletions src/transport/raw/MessageHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <type_traits>

#include <lib/core/CHIPError.h>
#include <lib/core/GroupId.h>
#include <lib/core/Optional.h>
#include <lib/core/PeerId.h>
#include <lib/support/BitFlags.h>
Expand Down Expand Up @@ -136,6 +137,13 @@ class PacketHeader
*/
const Optional<NodeId> & GetDestinationNodeId() const { return mDestinationNodeId; }

/**
* Gets the destination group id in the current message.
*
* NOTE: the destination group id is optional and may be missing.
*/
const Optional<GroupId> & GetDestinationGroupId() const { return mDestinationGroupId; }

uint16_t GetSessionId() const { return mSessionId; }

Header::Flags & GetFlags() { return mFlags; }
Expand Down Expand Up @@ -194,6 +202,27 @@ class PacketHeader
return *this;
}

PacketHeader & SetDestinationGroupId(GroupId id)
{
mDestinationGroupId.SetValue(id);
mFlags.Set(Header::FlagValues::kDestinationGroupIdPresent);
return *this;
}

PacketHeader & SetDestinationGroupId(Optional<GroupId> id)
{
mDestinationGroupId = id;
mFlags.Set(Header::FlagValues::kDestinationGroupIdPresent, id.HasValue());
return *this;
}

PacketHeader & ClearDestinationGroupId()
{
mDestinationGroupId.ClearValue();
mFlags.Clear(Header::FlagValues::kDestinationGroupIdPresent);
return *this;
}

PacketHeader & SetSessionId(uint16_t id)
{
mSessionId = id;
Expand Down Expand Up @@ -304,6 +333,7 @@ class PacketHeader

/// Intended recipient of the message.
Optional<NodeId> mDestinationNodeId;
Optional<GroupId> mDestinationGroupId;

/// Session ID
uint16_t mSessionId = kMsgSessionIdUnsecured;
Expand Down
31 changes: 31 additions & 0 deletions src/transport/raw/tests/TestMessageHeader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void TestPacketHeaderInitialState(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, header.GetMessageCounter() == 0);
NL_TEST_ASSERT(inSuite, header.GetSessionId() == 0);
NL_TEST_ASSERT(inSuite, !header.GetDestinationNodeId().HasValue());
NL_TEST_ASSERT(inSuite, !header.GetDestinationGroupId().HasValue());
NL_TEST_ASSERT(inSuite, !header.GetSourceNodeId().HasValue());
}

Expand Down Expand Up @@ -137,6 +138,20 @@ void TestPacketHeaderEncodeDecode(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, header.GetMessageCounter() == 234);
NL_TEST_ASSERT(inSuite, header.GetDestinationNodeId() == Optional<uint64_t>::Value(88ull));
NL_TEST_ASSERT(inSuite, header.GetSourceNodeId() == Optional<uint64_t>::Value(77ull));

// Verify Group Id helpers
header.SetMessageCounter(234).SetSourceNodeId(77).SetDestinationGroupId(45);
NL_TEST_ASSERT(inSuite, header.Encode(buffer, &encodeLen) == CHIP_ERROR_INTERNAL);

header.ClearDestinationNodeId();
NL_TEST_ASSERT(inSuite, header.Encode(buffer, &encodeLen) == CHIP_NO_ERROR);

// change it to verify decoding
header.SetMessageCounter(222).SetSourceNodeId(1).SetDestinationGroupId(2);
NL_TEST_ASSERT(inSuite, header.Decode(buffer, &decodeLen) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, header.GetMessageCounter() == 234);
NL_TEST_ASSERT(inSuite, header.GetDestinationGroupId() == Optional<uint16_t>::Value((uint16_t) 45));
NL_TEST_ASSERT(inSuite, header.GetSourceNodeId() == Optional<uint64_t>::Value(77ull));
}

void TestPayloadHeaderEncodeDecode(nlTestSuite * inSuite, void * inContext)
Expand Down Expand Up @@ -235,6 +250,22 @@ void TestPacketHeaderEncodeDecodeBounds(nlTestSuite * inSuite, void * inContext)
}
NL_TEST_ASSERT(inSuite, header.Decode(buffer, encoded_len, &decoded_len) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, decoded_len == encoded_len);

// Now test encoding/decoding with a source node id and destination group id present.
header.ClearDestinationNodeId();
header.SetDestinationGroupId(25);
for (uint16_t shortLen = minLen; shortLen < minLen + 10; shortLen++)
{
NL_TEST_ASSERT(inSuite, header.Encode(buffer, shortLen, &unusedLen) != CHIP_NO_ERROR);
}
NL_TEST_ASSERT(inSuite, header.Encode(buffer, minLen + 10, &encoded_len) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, encoded_len == minLen + 10);
for (uint16_t shortLen = 0; shortLen < encoded_len; shortLen++)
{
NL_TEST_ASSERT(inSuite, header.Decode(buffer, shortLen, &unusedLen) != CHIP_NO_ERROR);
}
NL_TEST_ASSERT(inSuite, header.Decode(buffer, encoded_len, &decoded_len) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, decoded_len == encoded_len);
}

void TestPayloadHeaderEncodeDecodeBounds(nlTestSuite * inSuite, void * inContext)
Expand Down

0 comments on commit cabc2f8

Please sign in to comment.