Skip to content

Commit cd2cd09

Browse files
Add ICD Sender Class (project-chip#30385)
1 parent 2fdbaf5 commit cd2cd09

9 files changed

+242
-13
lines changed

src/app/icd/BUILD.gn

+15
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,25 @@ source_set("manager") {
4242
":cluster",
4343
":notifier",
4444
":observer",
45+
":sender",
4546
"${chip_root}/src/credentials:credentials",
4647
]
4748
}
4849

50+
source_set("sender") {
51+
sources = [
52+
"ICDCheckInSender.cpp",
53+
"ICDCheckInSender.h",
54+
]
55+
56+
public_deps = [
57+
":cluster",
58+
"${chip_root}/src/credentials:credentials",
59+
"${chip_root}/src/lib/address_resolve:address_resolve",
60+
"${chip_root}/src/protocols/secure_channel",
61+
]
62+
}
63+
4964
# ICD management cluster source-set is broken out of the main source-set to enable unit tests
5065
# All sources and configurations used by the ICD management cluster need to go in this source-set
5166
source_set("cluster") {

src/app/icd/ICDCheckInSender.cpp

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
*
3+
* Copyright (c) 2023 Project CHIP Authors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "ICDCheckInSender.h"
19+
20+
#include <system/SystemPacketBuffer.h>
21+
22+
#include <protocols/secure_channel/CheckinMessage.h>
23+
24+
#include <lib/dnssd/Resolver.h>
25+
26+
namespace chip {
27+
namespace app {
28+
29+
using namespace Protocols::SecureChannel;
30+
31+
ICDCheckInSender::ICDCheckInSender(Messaging::ExchangeManager * exchangeManager)
32+
{
33+
VerifyOrDie(exchangeManager != nullptr);
34+
mExchangeManager = exchangeManager;
35+
mAddressLookupHandle.SetListener(this);
36+
}
37+
38+
void ICDCheckInSender::OnNodeAddressResolved(const PeerId & peerId, const AddressResolve::ResolveResult & result)
39+
{
40+
mResolveInProgress = false;
41+
42+
VerifyOrReturn(CHIP_NO_ERROR != SendCheckInMsg(result.address),
43+
ChipLogError(AppServer, "Failed to send the ICD Check-In message"));
44+
}
45+
46+
void ICDCheckInSender::OnNodeAddressResolutionFailed(const PeerId & peerId, CHIP_ERROR reason)
47+
{
48+
mResolveInProgress = false;
49+
ChipLogProgress(AppServer, "Node Address resolution failed for ICD Check-In with Node ID " ChipLogFormatX64,
50+
ChipLogValueX64(peerId.GetNodeId()));
51+
}
52+
53+
CHIP_ERROR ICDCheckInSender::SendCheckInMsg(const Transport::PeerAddress & addr)
54+
{
55+
System::PacketBufferHandle buffer = MessagePacketBuffer::New(CheckinMessage::sMinPayloadSize);
56+
57+
VerifyOrReturnError(!buffer.IsNull(), CHIP_ERROR_NO_MEMORY);
58+
MutableByteSpan output{ buffer->Start(), buffer->DataLength() };
59+
60+
// TODO retrieve Check-in counter
61+
CounterType counter = 0;
62+
63+
ReturnErrorOnFailure(CheckinMessage::GenerateCheckinMessagePayload(mKey, counter, ByteSpan(), output));
64+
65+
VerifyOrReturnError(mExchangeManager->GetSessionManager() != nullptr, CHIP_ERROR_INTERNAL);
66+
67+
Optional<SessionHandle> session =
68+
mExchangeManager->GetSessionManager()->CreateUnauthenticatedSession(addr, GetDefaultMRPConfig());
69+
VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);
70+
71+
// Using default MRP since we are not doing MRP in this context
72+
Messaging::ExchangeContext * exchangeContext = mExchangeManager->NewContext(session.Value(), nullptr);
73+
74+
VerifyOrReturnError(exchangeContext != nullptr, CHIP_ERROR_NO_MEMORY);
75+
76+
return exchangeContext->SendMessage(MsgType::ICD_CheckIn, std::move(buffer), Messaging::SendMessageFlags::kNoAutoRequestAck);
77+
}
78+
79+
CHIP_ERROR ICDCheckInSender::RequestResolve(ICDMonitoringEntry & entry, FabricTable * fabricTable)
80+
{
81+
VerifyOrReturnError(entry.IsValid(), CHIP_ERROR_INTERNAL);
82+
VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INTERNAL);
83+
const FabricInfo * fabricInfo = fabricTable->FindFabricWithIndex(entry.fabricIndex);
84+
PeerId peerId(fabricInfo->GetCompressedFabricId(), entry.checkInNodeID);
85+
86+
AddressResolve::NodeLookupRequest request(peerId);
87+
88+
memcpy(mKey.AsMutable<Crypto::Aes128KeyByteArray>(), entry.key.As<Crypto::Aes128KeyByteArray>(),
89+
sizeof(Crypto::Aes128KeyByteArray));
90+
91+
// TODO #30492
92+
// Device must stay active during MDNS resolution
93+
CHIP_ERROR err = AddressResolve::Resolver::Instance().LookupNode(request, mAddressLookupHandle);
94+
95+
if (err == CHIP_NO_ERROR)
96+
{
97+
mResolveInProgress = true;
98+
}
99+
100+
return err;
101+
}
102+
103+
} // namespace app
104+
} // namespace chip

src/app/icd/ICDCheckInSender.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
*
3+
* Copyright (c) 2023 Project CHIP Authors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#pragma once
18+
19+
#include <app/icd/ICDMonitoringTable.h>
20+
#include <credentials/FabricTable.h>
21+
#include <lib/address_resolve/AddressResolve.h>
22+
23+
#include <messaging/ExchangeMgr.h>
24+
25+
namespace chip {
26+
namespace app {
27+
28+
/**
29+
* @brief ICD Check-In Sender is responsible for resolving the NodeId and sending the check-in message
30+
*/
31+
class ICDCheckInSender : public AddressResolve::NodeListener
32+
{
33+
public:
34+
ICDCheckInSender(Messaging::ExchangeManager * exchangeManager);
35+
~ICDCheckInSender(){};
36+
37+
CHIP_ERROR RequestResolve(ICDMonitoringEntry & entry, FabricTable * fabricTable);
38+
39+
// AddressResolve::NodeListener - notifications when dnssd finds a node IP address
40+
void OnNodeAddressResolved(const PeerId & peerId, const AddressResolve::ResolveResult & result) override;
41+
void OnNodeAddressResolutionFailed(const PeerId & peerId, CHIP_ERROR reason) override;
42+
43+
bool mResolveInProgress = false;
44+
45+
private:
46+
CHIP_ERROR SendCheckInMsg(const Transport::PeerAddress & addr);
47+
48+
// This is used when a node address is required.
49+
AddressResolve::NodeLookupHandle mAddressLookupHandle;
50+
51+
Messaging::ExchangeManager * mExchangeManager = nullptr;
52+
53+
Crypto::Aes128KeyHandle mKey = Crypto::Aes128KeyHandle();
54+
};
55+
56+
} // namespace app
57+
} // namespace chip

src/app/icd/ICDMonitoringTable.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,25 @@ bool ICDMonitoringEntry::IsKeyEquivalent(ByteSpan keyData)
161161
return (data == validation) ? true : false;
162162
}
163163

164+
ICDMonitoringEntry & ICDMonitoringEntry::operator=(const ICDMonitoringEntry & icdMonitoringEntry)
165+
{
166+
if (this == &icdMonitoringEntry)
167+
{
168+
return *this;
169+
}
170+
171+
fabricIndex = icdMonitoringEntry.fabricIndex;
172+
checkInNodeID = icdMonitoringEntry.checkInNodeID;
173+
monitoredSubject = icdMonitoringEntry.monitoredSubject;
174+
index = icdMonitoringEntry.index;
175+
keyHandleValid = icdMonitoringEntry.keyHandleValid;
176+
symmetricKeystore = icdMonitoringEntry.symmetricKeystore;
177+
memcpy(key.AsMutable<Crypto::Aes128KeyByteArray>(), icdMonitoringEntry.key.As<Crypto::Aes128KeyByteArray>(),
178+
sizeof(Crypto::Aes128KeyByteArray));
179+
180+
return *this;
181+
}
182+
164183
CHIP_ERROR ICDMonitoringTable::Get(uint16_t index, ICDMonitoringEntry & entry) const
165184
{
166185
entry.fabricIndex = this->mFabric;

src/app/icd/ICDMonitoringTable.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ struct ICDMonitoringEntry : public PersistentData<kICDMonitoringBufferSize>
5454
this->symmetricKeystore = keyStore;
5555
}
5656

57-
bool IsValid() { return this->checkInNodeID != kUndefinedNodeId && this->fabricIndex != kUndefinedFabricIndex; }
5857
CHIP_ERROR UpdateKey(StorageKeyName & key) override;
5958
CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override;
6059
CHIP_ERROR Deserialize(TLV::TLVReader & reader) override;
@@ -77,6 +76,13 @@ struct ICDMonitoringEntry : public PersistentData<kICDMonitoringBufferSize>
7776
*/
7877
CHIP_ERROR SetKey(ByteSpan keyData);
7978
CHIP_ERROR DeleteKey(void);
79+
inline bool IsValid()
80+
{
81+
return (symmetricKeystore != nullptr && keyHandleValid && fabricIndex != kUndefinedFabricIndex &&
82+
checkInNodeID != kUndefinedNodeId);
83+
}
84+
85+
ICDMonitoringEntry & operator=(const ICDMonitoringEntry & icdMonitoringEntry);
8086

8187
/**
8288
* @brief Implement the key verification needed by the ICDManagement Server.

src/app/tests/TestICDMonitoringTable.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,39 @@ constexpr uint8_t kKeyBuffer3a[] = {
6161
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
6262
};
6363

64+
void TestEntryAssignationOverload(nlTestSuite * aSuite, void * aContext)
65+
{
66+
TestSessionKeystoreImpl keystore;
67+
ICDMonitoringEntry entry(&keystore);
68+
69+
// Test Setting Key
70+
NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == entry.SetKey(ByteSpan(kKeyBuffer1a)));
71+
72+
entry.fabricIndex = 2;
73+
74+
NL_TEST_ASSERT(aSuite, !entry.IsValid());
75+
76+
entry.checkInNodeID = 34;
77+
entry.monitoredSubject = 32;
78+
79+
// Entry should be valid now
80+
NL_TEST_ASSERT(aSuite, entry.IsValid());
81+
82+
ICDMonitoringEntry entry2;
83+
84+
NL_TEST_ASSERT(aSuite, !entry2.IsValid());
85+
86+
entry2 = entry;
87+
88+
NL_TEST_ASSERT(aSuite, entry2.IsValid());
89+
90+
NL_TEST_ASSERT(aSuite, entry2.fabricIndex == entry.fabricIndex);
91+
NL_TEST_ASSERT(aSuite, entry2.checkInNodeID == entry.checkInNodeID);
92+
NL_TEST_ASSERT(aSuite, entry2.monitoredSubject == entry.monitoredSubject);
93+
94+
NL_TEST_ASSERT(aSuite, entry.IsKeyEquivalent(ByteSpan(entry2.key.As<Crypto::Aes128KeyByteArray>())));
95+
}
96+
6497
void TestEntryKeyFunctions(nlTestSuite * aSuite, void * aContext)
6598
{
6699
TestSessionKeystoreImpl keystore;
@@ -393,6 +426,7 @@ int Test_Setup(void * inContext)
393426
int TestClientMonitoringRegistrationTable()
394427
{
395428
static nlTest sTests[] = { NL_TEST_DEF("TestEntryKeyFunctions", TestEntryKeyFunctions),
429+
NL_TEST_DEF("TestEntryAssignationOverload", TestEntryAssignationOverload),
396430
NL_TEST_DEF("TestSaveAndLoadRegistrationValue", TestSaveAndLoadRegistrationValue),
397431
NL_TEST_DEF("TestSaveAllInvalidRegistrationValues", TestSaveAllInvalidRegistrationValues),
398432
NL_TEST_DEF("TestSaveLoadRegistrationValueForMultipleFabrics",

src/messaging/BUILD.gn

-4
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,4 @@ static_library("messaging") {
7777
"${chip_root}/src/transport",
7878
"${chip_root}/src/transport/raw",
7979
]
80-
81-
if (chip_enable_icd_server) {
82-
public_deps += [ "${chip_root}/src/app/icd:manager" ]
83-
}
8480
}

src/messaging/ReliableMessageProtocolConfig.cpp

+4-7
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@
2727
#include <platform/CHIPDeviceLayer.h>
2828
#include <system/SystemClock.h>
2929

30-
#if CHIP_CONFIG_ENABLE_ICD_SERVER
31-
#include <app/icd/ICDManagementServer.h> // nogncheck
32-
#include <app/icd/ICDManager.h> // nogncheck
33-
#endif
30+
#include <platform/CHIPDeviceConfig.h>
3431

3532
namespace chip {
3633

@@ -73,9 +70,9 @@ Optional<ReliableMessageProtocolConfig> GetLocalMRPConfig()
7370
// TODO ICD LIT shall not advertise the SII key
7471
// Increase local MRP retry intervals by ICD polling intervals. That is, intervals for
7572
// which the device can be at sleep and not be able to receive any messages).
76-
config.mIdleRetransTimeout += app::ICDManager::GetSlowPollingInterval();
77-
config.mActiveRetransTimeout += app::ICDManager::GetFastPollingInterval();
78-
config.mActiveThresholdTime = System::Clock::Milliseconds16(ICDManagementServer::GetInstance().GetActiveModeThresholdMs());
73+
config.mIdleRetransTimeout += CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL;
74+
config.mActiveRetransTimeout += CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL;
75+
config.mActiveThresholdTime = System::Clock::Milliseconds16(CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS);
7976
#endif
8077

8178
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST

src/platform/Linux/BUILD.gn

+2-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ static_library("Linux") {
109109
"${chip_root}/third_party/inipp",
110110
]
111111

112-
public_configs = []
112+
public_configs =
113+
[ "${chip_root}/src/lib/address_resolve:default_address_resolve_config" ]
113114

114115
if (chip_mdns == "platform") {
115116
sources += [

0 commit comments

Comments
 (0)