Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StandaloneAck handling: Untangle code path for UMH and StandaloneAck #3

Closed
Closed
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5d8599d
Updating Infineon P6 all clusters and all clusters minimal apps (#19245)
keithmwheeler Jun 9, 2022
fbe49dd
Run media cluster tests in tv-app in CI. (#19325)
bzbarsky-apple Jun 9, 2022
bdac2dc
Added Manual Scripts (#19286)
kowsisoundhar12 Jun 9, 2022
d9cfd7e
[EFR32] Lock-app updates, adding multiple users and credentials (#19229)
mykrupp Jun 9, 2022
ac8bdbf
[Zephyr] Support heap watermark for non-default malloc (#19385)
Damian-Nordic Jun 9, 2022
b943909
Remove SystemLayerImplLibevent (#19396)
kpschoedel Jun 9, 2022
d2e5909
[pump] PostEvents now called from ScheduleWork (#19379)
ReneJosefsen Jun 9, 2022
3b8810d
doc: nrf_connect: rework OT RCP dongle guide (#19374)
greg-fer Jun 9, 2022
195181b
Fix K32W061 issues (#19372)
doru91 Jun 9, 2022
0adc4f3
Bugfix: Dont read non-existing attributes for lock/unlock commands (#…
Morozov-5F Jun 9, 2022
44a6f1b
[nrfconnect] Created a CMAKE script to generate factory data (#19153)
ArekBalysNordic Jun 9, 2022
cba9187
Respect maximum log level in esp32 pw_hdlc logger (#19401)
mspang Jun 9, 2022
668938e
Update TestListStructOctet to use member names that are generic (#19321)
tehampson Jun 9, 2022
47c8653
[thread] use MLE Discovery mechanism instead of active scanning (#19200)
LuDuda Jun 10, 2022
96f83a0
AddGroup Command with the GroupID as 0 now responds as INVALID_COMMAN…
rcasallas-silabs Jun 10, 2022
8b16650
Chef - Use temporary folder for stateful_shell artifacts (#19362)
cpagravel Jun 10, 2022
c2a869a
[1/3] Reserve `SecureSession` for CASE establishment on the responder…
mrjerryjohns Jun 10, 2022
b16ddb3
Fix compiling errors for ESP32H2 (#19365)
wqx6 Jun 10, 2022
3522f9a
Bridge app test updates (#18858)
jwinder-ca Jun 10, 2022
10a5389
Ensure that we send MRP acks to incoming messages as needed. (#19398)
bzbarsky-apple Jun 10, 2022
6bb052e
StandaloneAck handling: Untangle code path for UMH and StandaloneAck
kghost Jun 10, 2022
01d544b
Fix comments from Boris
kghost Jun 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[1/3] Reserve SecureSession for CASE establishment on the responder…
… at init time (project-chip#19261)

* Initial commit.

* Review feedback

* Review feedback

* Minor integer promotion issue in a test

* Linux build fix
mrjerryjohns authored Jun 10, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit c2a869af7610a8c0ada738c3b7e73c2640147674
1 change: 1 addition & 0 deletions src/app/server/Server.cpp
Original file line number Diff line number Diff line change
@@ -348,6 +348,7 @@ void Server::ScheduleFactoryReset()

void Server::Shutdown()
{
mCASEServer.Shutdown();
mCASESessionManager.Shutdown();
app::DnssdServer::Instance().SetCommissioningModeProvider(nullptr);
chip::Dnssd::ServiceAdvertiser::Instance().Shutdown();
1 change: 1 addition & 0 deletions src/controller/CHIPDeviceControllerFactory.cpp
Original file line number Diff line number Diff line change
@@ -339,6 +339,7 @@ CHIP_ERROR DeviceControllerSystemState::Shutdown()

if (mCASEServer != nullptr)
{
mCASEServer->Shutdown();
chip::Platform::Delete(mCASEServer);
mCASEServer = nullptr;
}
20 changes: 13 additions & 7 deletions src/lib/core/CHIPConfig.h
Original file line number Diff line number Diff line change
@@ -644,15 +644,21 @@
#endif // CHIP_CONFIG_UNAUTHENTICATED_CONNECTION_POOL_SIZE

/**
* @def CHIP_CONFIG_PEER_CONNECTION_POOL_SIZE
* @def CHIP_CONFIG_SECURE_SESSION_POOL_SIZE
*
* @brief Defines the size of the pool used for tracking the state of
* secure sessions. This controls the maximum number of concurrent
* established secure sessions across all supported transports.
*
* This is sized to cover the sum of the following:
* - At least 3 CASE sessions / fabric (Spec Ref: 4.13.2.8)
* - 1 reserved slot for CASEServer as a responder.
* - 1 reserved slot for PASE.
*
* @brief Define the size of the pool used for tracking CHIP
* Peer connections. This defines maximum number of concurrent
* device connections across all supported transports.
*/
#ifndef CHIP_CONFIG_PEER_CONNECTION_POOL_SIZE
#define CHIP_CONFIG_PEER_CONNECTION_POOL_SIZE 16
#endif // CHIP_CONFIG_PEER_CONNECTION_POOL_SIZE
#ifndef CHIP_CONFIG_SECURE_SESSION_POOL_SIZE
#define CHIP_CONFIG_SECURE_SESSION_POOL_SIZE (CHIP_CONFIG_MAX_FABRICS * 3 + 2)
#endif // CHIP_CONFIG_SECURE_SESSION_POOL_SIZE

/**
* @def CHIP_CONFIG_SECURE_SESSION_REFCOUNT_LOGGING
60 changes: 49 additions & 11 deletions src/protocols/secure_channel/CASEServer.cpp
Original file line number Diff line number Diff line change
@@ -45,20 +45,18 @@ CHIP_ERROR CASEServer::ListenForSessionEstablishment(Messaging::ExchangeManager
mExchangeManager = exchangeManager;
mGroupDataProvider = responderGroupDataProvider;

Cleanup();
// Set up the group state provider that persists across all handshakes.
GetSession().SetGroupDataProvider(mGroupDataProvider);

PrepareForSessionEstablishment();

return CHIP_NO_ERROR;
}

CHIP_ERROR CASEServer::InitCASEHandshake(Messaging::ExchangeContext * ec)
{
ReturnErrorCodeIf(ec == nullptr, CHIP_ERROR_INVALID_ARGUMENT);

// Setup CASE state machine using the credentials for the current fabric.
GetSession().SetGroupDataProvider(mGroupDataProvider);
ReturnErrorOnFailure(GetSession().ListenForSessionEstablishment(
*mSessionManager, mFabrics, mSessionResumptionStorage, mCertificateValidityPolicy, this,
Optional<ReliableMessageProtocolConfig>::Value(GetLocalMRPConfig())));

// Hand over the exchange context to the CASE session.
ec->SetDelegate(&GetSession());

@@ -90,31 +88,71 @@ CHIP_ERROR CASEServer::OnMessageReceived(Messaging::ExchangeContext * ec, const
exit:
if (err != CHIP_NO_ERROR)
{
Cleanup();
PrepareForSessionEstablishment();
}

return err;
}

void CASEServer::Cleanup()
void CASEServer::PrepareForSessionEstablishment(const ScopedNodeId & previouslyEstablishedPeer)
{
// Let's re-register for CASE Sigma1 message, so that the next CASE session setup request can be processed.
// https://github.com/project-chip/connectedhomeip/issues/8342
ChipLogProgress(Inet, "CASE Server enabling CASE session setups");
mExchangeManager->RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::CASE_Sigma1, this);

GetSession().Clear();

//
// Indicate to the underlying CASE session to prepare for session establishment requests coming its way. This will
// involve allocating a SecureSession that will be held until it's needed for the next CASE session handshake.
//
// Logically speaking, we're attempting to evict a session using details of the just-established session (to ensure
// we're evicting sessions from the right fabric if needed) and then transferring the just established session into that
// slot (and thereby free'ing up the slot for the next session attempt). However, this transfer isn't necessary - just
// evicting a session will ensure it is available for the next attempt.
//
// This call can fail if we have run out memory to allocate SecureSessions. Continuing without taking any action
// however will render this node deaf to future handshake requests, so it's better to die here to raise attention to the problem
// / facilitate recovery.
//
// TODO(#17568): Once session eviction is actually in place, this call should NEVER fail and if so, is a logic bug.
// Dying here on failure is even more appropriate then.
//
VerifyOrDie(GetSession().PrepareForSessionEstablishment(*mSessionManager, mFabrics, mSessionResumptionStorage,
mCertificateValidityPolicy, this, previouslyEstablishedPeer,
Optional<ReliableMessageProtocolConfig>::Value(GetLocalMRPConfig())) ==
CHIP_NO_ERROR);

//
// PairingSession::mSecureSessionHolder is a weak-reference. If MarkForRemoval is called on this session, the session is
// going to get de-allocated from underneath us. This session that has just been allocated should *never* get evicted, and
// remain available till the next hand-shake is received.
//
// TODO: Converting SessionHolder to a true weak-ref and making PairingSession hold a strong-ref (#18397) would avoid this
// headache...
//
// Let's create a SessionHandle strong-reference to it to keep it resident.
//
mPinnedSecureSession = GetSession().CopySecureSession();

//
// If we've gotten this far, it means we have successfully allocated a SecureSession to back our next attempt. If we haven't,
// there is a bug somewhere and we should raise attention to it by dying.
//
VerifyOrDie(mPinnedSecureSession.HasValue());
}

void CASEServer::OnSessionEstablishmentError(CHIP_ERROR err)
{
ChipLogError(Inet, "CASE Session establishment failed: %s", ErrorStr(err));
Cleanup();
PrepareForSessionEstablishment();
}

void CASEServer::OnSessionEstablished(const SessionHandle & session)
{
ChipLogProgress(Inet, "CASE Session established to peer: " ChipLogFormatScopedNodeId,
ChipLogValueScopedNodeId(session->GetPeer()));
Cleanup();
PrepareForSessionEstablishment(session->GetPeer());
}
} // namespace chip
37 changes: 35 additions & 2 deletions src/protocols/secure_channel/CASEServer.h
Original file line number Diff line number Diff line change
@@ -31,12 +31,23 @@ class CASEServer : public SessionEstablishmentDelegate,
{
public:
CASEServer() {}
~CASEServer() override
~CASEServer() override { Shutdown(); }

/*
* This method will shutdown this object, releasing the strong reference to the pinned SecureSession object.
* It will also unregister the unsolicited handler and clear out the session object (which will release the weak
* reference through the underlying SessionHolder).
*
*/
void Shutdown()
{
if (mExchangeManager != nullptr)
{
mExchangeManager->UnregisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::CASE_Sigma1);
}

GetSession().Clear();
mPinnedSecureSession.ClearValue();
}

CHIP_ERROR ListenForSessionEstablishment(Messaging::ExchangeManager * exchangeManager, SessionManager * sessionManager,
@@ -64,6 +75,19 @@ class CASEServer : public SessionEstablishmentDelegate,
SessionResumptionStorage * mSessionResumptionStorage = nullptr;
Credentials::CertificateValidityPolicy * mCertificateValidityPolicy = nullptr;

//
// When we're in the process of establishing a session, this is used
// to maintain an additional, strong reference to the underlying SecureSession.
// This is because the existing reference in PairingSession is a weak one
// (i.e a SessionHolder) and can lose its reference if the session is evicted
// for any reason.
//
// This initially points to a session that is not yet active. Upon activation, it
// transfers ownership of the session to the SecureSessionManager and this reference
// is released before simultaneously acquiring ownership of a new SecureSession.
//
Optional<SessionHandle> mPinnedSecureSession;

CASESession mPairingSession;
SessionManager * mSessionManager = nullptr;

@@ -72,7 +96,16 @@ class CASEServer : public SessionEstablishmentDelegate,

CHIP_ERROR InitCASEHandshake(Messaging::ExchangeContext * ec);

void Cleanup();
/*
* This will clean up any state from a previous session establishment
* attempt (if any) and setup the machinery to listen for and handle
* any session handshakes there-after.
*
* If a session had previously been established successfully, previouslyEstablishedPeer
* should be set to the scoped node-id of the peer associated with that session.
*
*/
void PrepareForSessionEstablishment(const ScopedNodeId & previouslyEstablishedPeer = ScopedNodeId());
};

} // namespace chip
17 changes: 9 additions & 8 deletions src/protocols/secure_channel/CASESession.cpp
Original file line number Diff line number Diff line change
@@ -151,7 +151,7 @@ void CASESession::Clear()
}

CHIP_ERROR CASESession::Init(SessionManager & sessionManager, Credentials::CertificateValidityPolicy * policy,
SessionEstablishmentDelegate * delegate)
SessionEstablishmentDelegate * delegate, const ScopedNodeId & sessionEvictionHint)
{
VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(mGroupDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
@@ -161,7 +161,7 @@ CHIP_ERROR CASESession::Init(SessionManager & sessionManager, Credentials::Certi
ReturnErrorOnFailure(mCommissioningHash.Begin());

mDelegate = delegate;
ReturnErrorOnFailure(AllocateSecureSession(sessionManager));
ReturnErrorOnFailure(AllocateSecureSession(sessionManager, sessionEvictionHint));

mValidContext.Reset();
mValidContext.mRequiredKeyUsages.Set(KeyUsageFlags::kDigitalSignature);
@@ -172,13 +172,14 @@ CHIP_ERROR CASESession::Init(SessionManager & sessionManager, Credentials::Certi
}

CHIP_ERROR
CASESession::ListenForSessionEstablishment(SessionManager & sessionManager, FabricTable * fabrics,
SessionResumptionStorage * sessionResumptionStorage,
Credentials::CertificateValidityPolicy * policy, SessionEstablishmentDelegate * delegate,
Optional<ReliableMessageProtocolConfig> mrpConfig)
CASESession::PrepareForSessionEstablishment(SessionManager & sessionManager, FabricTable * fabrics,
SessionResumptionStorage * sessionResumptionStorage,
Credentials::CertificateValidityPolicy * policy,
SessionEstablishmentDelegate * delegate, ScopedNodeId previouslyEstablishedPeer,
Optional<ReliableMessageProtocolConfig> mrpConfig)
{
VerifyOrReturnError(fabrics != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorOnFailure(Init(sessionManager, policy, delegate));
ReturnErrorOnFailure(Init(sessionManager, policy, delegate, previouslyEstablishedPeer));

mRole = CryptoContext::SessionRole::kResponder;
mFabricsTable = fabrics;
@@ -207,7 +208,7 @@ CHIP_ERROR CASESession::EstablishSession(SessionManager & sessionManager, Fabric
ReturnErrorCodeIf(fabricIndex == kUndefinedFabricIndex, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError((fabricInfo = fabricTable->FindFabricWithIndex(fabricIndex)) != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

err = Init(sessionManager, policy, delegate);
err = Init(sessionManager, policy, delegate, ScopedNodeId(peerNodeId, fabricIndex));

mRole = CryptoContext::SessionRole::kInitiator;

18 changes: 16 additions & 2 deletions src/protocols/secure_channel/CASESession.h
Original file line number Diff line number Diff line change
@@ -75,12 +75,17 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler,
* @param fabrics Table of fabrics that are currently configured on the device
* @param policy Optional application-provided certificate validity policy
* @param delegate Callback object
* @param previouslyEstablishedPeer If a session had previously been established successfully to a peer, this should
* be set to its scoped node-id. Else, this should be initialized to a
* default-constructed ScopedNodeId().
* @param mrpConfig MRP configuration to encode into Sigma2. If not provided, it won't be encoded.
*
* @return CHIP_ERROR The result of initialization
*/
CHIP_ERROR ListenForSessionEstablishment(
CHIP_ERROR PrepareForSessionEstablishment(
SessionManager & sessionManager, FabricTable * fabrics, SessionResumptionStorage * sessionResumptionStorage,
Credentials::CertificateValidityPolicy * policy, SessionEstablishmentDelegate * delegate,
ScopedNodeId previouslyEstablishedPeer,
Optional<ReliableMessageProtocolConfig> mrpConfig = Optional<ReliableMessageProtocolConfig>::Missing());

/**
@@ -181,8 +186,17 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler,
kFinishedViaResume = 7,
};

/*
* Initialize the object given a reference to the SessionManager, certificate validity policy and a delegate which will be
* notified of any further progress on this session.
*
* If we're either establishing or finished establishing a session to a peer in either initiator or responder
* roles, the node id of that peer should be provided in sessionEvictionHint. Else, it should be initialized
* to a default-constructed ScopedNodeId().
*
*/
CHIP_ERROR Init(SessionManager & sessionManager, Credentials::CertificateValidityPolicy * policy,
SessionEstablishmentDelegate * delegate);
SessionEstablishmentDelegate * delegate, const ScopedNodeId & sessionEvictionHint);

// On success, sets mIpk to the correct value for outgoing Sigma1 based on internal state
CHIP_ERROR RecoverInitiatorIpk();
4 changes: 2 additions & 2 deletions src/protocols/secure_channel/PairingSession.cpp
Original file line number Diff line number Diff line change
@@ -23,9 +23,9 @@

namespace chip {

CHIP_ERROR PairingSession::AllocateSecureSession(SessionManager & sessionManager)
CHIP_ERROR PairingSession::AllocateSecureSession(SessionManager & sessionManager, const ScopedNodeId & sessionEvictionHint)
{
auto handle = sessionManager.AllocateSession(GetSecureSessionType());
auto handle = sessionManager.AllocateSession(GetSecureSessionType(), sessionEvictionHint);
VerifyOrReturnError(handle.HasValue(), CHIP_ERROR_NO_MEMORY);
VerifyOrReturnError(mSecureSessionHolder.GrabPairingSession(handle.Value()), CHIP_ERROR_INTERNAL);
mSessionManager = &sessionManager;
24 changes: 22 additions & 2 deletions src/protocols/secure_channel/PairingSession.h
Original file line number Diff line number Diff line change
@@ -63,11 +63,27 @@ class DLL_EXPORT PairingSession : public SessionDelegate
return localSessionId;
}

/**
* Copy the underlying session (if present) into a SessionHandle that a caller can use to
* obtain a reference to the session.
*/
Optional<SessionHandle> CopySecureSession()
{
if (mSecureSessionHolder)
{
VerifyOrDie(mSecureSessionHolder->GetSessionType() == Transport::Session::SessionType::kSecure);
return MakeOptional<SessionHandle>(*mSecureSessionHolder->AsSecureSession());
}

return Optional<SessionHandle>::Missing();
}

uint16_t GetPeerSessionId() const
{
VerifyOrDie(mPeerSessionId.HasValue());
return mPeerSessionId.Value();
}

bool IsValidPeerSessionId() const { return mPeerSessionId.HasValue(); }

/**
@@ -93,10 +109,14 @@ class DLL_EXPORT PairingSession : public SessionDelegate
* Allocate a secure session object from the passed session manager for the
* pending session establishment operation.
*
* @param sessionManager session manager from which to allocate a secure session object
* @param sessionManager Session manager from which to allocate a secure session object
* @param sessionEvictionHint If we're either establishing or just finished establishing a session to a peer in either
* initiator or responder roles, the node id of that peer should be provided in this argument. Else, it should be initialized to
* a default-constructed ScopedNodeId().
*
* @return CHIP_ERROR The outcome of the allocation attempt
*/
CHIP_ERROR AllocateSecureSession(SessionManager & sessionManager);
CHIP_ERROR AllocateSecureSession(SessionManager & sessionManager, const ScopedNodeId & sessionEvictionHint = ScopedNodeId());

CHIP_ERROR ActivateSecureSession(const Transport::PeerAddress & peerAddress);

14 changes: 8 additions & 6 deletions src/protocols/secure_channel/tests/TestCASESession.cpp
Original file line number Diff line number Diff line change
@@ -198,13 +198,14 @@ void CASE_SecurePairingWaitTest(nlTestSuite * inSuite, void * inContext)

pairing.SetGroupDataProvider(&gDeviceGroupDataProvider);
NL_TEST_ASSERT(inSuite,
pairing.ListenForSessionEstablishment(sessionManager, nullptr, nullptr, nullptr, nullptr) ==
pairing.PrepareForSessionEstablishment(sessionManager, nullptr, nullptr, nullptr, nullptr, ScopedNodeId()) ==
CHIP_ERROR_INVALID_ARGUMENT);
NL_TEST_ASSERT(inSuite,
pairing.ListenForSessionEstablishment(sessionManager, nullptr, nullptr, nullptr, &delegate) ==
pairing.PrepareForSessionEstablishment(sessionManager, nullptr, nullptr, nullptr, &delegate, ScopedNodeId()) ==
CHIP_ERROR_INVALID_ARGUMENT);
NL_TEST_ASSERT(inSuite,
pairing.ListenForSessionEstablishment(sessionManager, &fabrics, nullptr, nullptr, &delegate) == CHIP_NO_ERROR);
pairing.PrepareForSessionEstablishment(sessionManager, &fabrics, nullptr, nullptr, &delegate, ScopedNodeId()) ==
CHIP_NO_ERROR);
}

void CASE_SecurePairingStartTest(nlTestSuite * inSuite, void * inContext)
@@ -283,9 +284,9 @@ void CASE_SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inConte

pairingAccessory.SetGroupDataProvider(&gDeviceGroupDataProvider);
NL_TEST_ASSERT(inSuite,
pairingAccessory.ListenForSessionEstablishment(sessionManager, &gDeviceFabrics, nullptr, nullptr,
&delegateAccessory,
MakeOptional(verySleepyAccessoryRmpConfig)) == CHIP_NO_ERROR);
pairingAccessory.PrepareForSessionEstablishment(sessionManager, &gDeviceFabrics, nullptr, nullptr,
&delegateAccessory, ScopedNodeId(),
MakeOptional(verySleepyAccessoryRmpConfig)) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite,
pairingCommissioner.EstablishSession(sessionManager, &gCommissionerFabrics, gCommissionerFabricIndex, Node01_01,
contextCommissioner, nullptr, nullptr, &delegateCommissioner,
@@ -847,6 +848,7 @@ int CASE_TestSecurePairing_Setup(void * inContext)
*/
int CASE_TestSecurePairing_Teardown(void * inContext)
{
gPairingServer.Shutdown();
gCommissionerStorageDelegate.ClearStorage();
gDeviceStorageDelegate.ClearStorage();
gCommissionerFabrics.DeleteAllFabrics();
2 changes: 1 addition & 1 deletion src/transport/SecureSessionTable.h
Original file line number Diff line number Diff line change
@@ -214,7 +214,7 @@ class SecureSessionTable
return NullOptional;
}

BitMapObjectPool<SecureSession, CHIP_CONFIG_PEER_CONNECTION_POOL_SIZE> mEntries;
BitMapObjectPool<SecureSession, CHIP_CONFIG_SECURE_SESSION_POOL_SIZE> mEntries;
uint16_t mNextSessionId = 0;
};

8 changes: 7 additions & 1 deletion src/transport/SessionManager.cpp
Original file line number Diff line number Diff line change
@@ -387,8 +387,14 @@ void SessionManager::ExpireAllPASEPairings()
});
}

Optional<SessionHandle> SessionManager::AllocateSession(SecureSession::Type secureSessionType)
Optional<SessionHandle> SessionManager::AllocateSession(SecureSession::Type secureSessionType,
const ScopedNodeId & sessionEvictionHint)
{
//
// This is currently not being utilized yet but will be once session eviction logic is added.
//
(void) sessionEvictionHint;

return mSecureSessions.CreateNewSecureSession(secureSessionType);
}

7 changes: 6 additions & 1 deletion src/transport/SessionManager.h
Original file line number Diff line number Diff line change
@@ -160,10 +160,15 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate
* Allocate a secure session and non-colliding session ID in the secure
* session table.
*
* If we're either establishing or just finished establishing a session to a peer in either initiator or responder
* roles, the node id of that peer should be provided in sessionEvictionHint. Else, it should be initialized
* to a default-constructed ScopedNodeId().
*
* @return SessionHandle with a reference to a SecureSession, else NullOptional on failure
*/
CHECK_RETURN_VALUE
Optional<SessionHandle> AllocateSession(Transport::SecureSession::Type secureSessionType);
Optional<SessionHandle> AllocateSession(Transport::SecureSession::Type secureSessionType,
const ScopedNodeId & sessionEvictionHint);

void ExpirePairing(const SessionHandle & session);
void ExpireAllPairings(const ScopedNodeId & node);
10 changes: 5 additions & 5 deletions src/transport/tests/TestPeerConnections.cpp
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ void TestBasicFunctionality(nlTestSuite * inSuite, void * inContext)
System::Clock::Internal::SetSystemClockForTesting(&clock);
clock.SetMonotonic(100_ms64);
CATValues peerCATs;
Optional<SessionHandle> sessions[CHIP_CONFIG_PEER_CONNECTION_POOL_SIZE];
Optional<SessionHandle> sessions[CHIP_CONFIG_SECURE_SESSION_POOL_SIZE];

// First node, peer session id 1, local session id 2
auto optionalSession = connections.CreateNewSecureSessionForTest(SecureSession::Type::kCASE, 2, kLocalNodeId, kCasePeer1NodeId,
@@ -97,11 +97,11 @@ void TestBasicFunctionality(nlTestSuite * inSuite, void * inContext)
// This define guard will be needed when migrating SecureSessionTable to ObjectPool
//#if !CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
// If not using a heap, we can fill the SecureSessionTable
for (uint16_t i = 2; i < CHIP_CONFIG_PEER_CONNECTION_POOL_SIZE; ++i)
for (int i = 2; i < CHIP_CONFIG_SECURE_SESSION_POOL_SIZE; ++i)
{
sessions[i] =
connections.CreateNewSecureSessionForTest(SecureSession::Type::kCASE, static_cast<uint16_t>(i + 6u), kLocalNodeId,
kCasePeer2NodeId, kPeer2CATs, 3, kFabricIndex, GetLocalMRPConfig());
sessions[i] = connections.CreateNewSecureSessionForTest(SecureSession::Type::kCASE,
static_cast<uint16_t>(static_cast<uint16_t>(i) + 6u), kLocalNodeId,
kCasePeer2NodeId, kPeer2CATs, 3, kFabricIndex, GetLocalMRPConfig());
NL_TEST_ASSERT(inSuite, sessions[i].HasValue());
}

26 changes: 19 additions & 7 deletions src/transport/tests/TestSessionManager.cpp
Original file line number Diff line number Diff line change
@@ -656,7 +656,9 @@ static void RandomSessionIdAllocatorOffset(nlTestSuite * inSuite, SessionManager
const int bound = rand() % max;
for (int i = 0; i < bound; ++i)
{
auto handle = sessionManager.AllocateSession(Transport::SecureSession::Type::kPASE);
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handle.HasValue());
sessionManager.ExpirePairing(handle.Value());
}
@@ -669,7 +671,9 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext)
// Allocate a session.
uint16_t sessionId1;
{
auto handle = sessionManager.AllocateSession(Transport::SecureSession::Type::kPASE);
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handle.HasValue());
SessionHolder session;
session.GrabPairingSession(handle.Value());
@@ -681,7 +685,9 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext)
auto prevSessionId = sessionId1;
for (uint32_t i = 0; i < 10; ++i)
{
auto handle = sessionManager.AllocateSession(Transport::SecureSession::Type::kPASE);
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
if (!handle.HasValue())
{
break;
@@ -702,7 +708,9 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext)
// sessions are immediately freed.
for (uint32_t i = 0; i < UINT16_MAX + 10; ++i)
{
auto handle = sessionManager.AllocateSession(Transport::SecureSession::Type::kPASE);
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handle.HasValue());
auto sessionId = handle.Value()->AsSecureSession()->GetLocalSessionId();
NL_TEST_ASSERT(inSuite, sessionId - prevSessionId == 1 || (sessionId == 1 && prevSessionId == 65535));
@@ -717,13 +725,15 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext)
{
// Allocate some session handles at pseudo-random offsets in the session
// ID space.
constexpr size_t numHandles = CHIP_CONFIG_PEER_CONNECTION_POOL_SIZE - 1;
constexpr size_t numHandles = CHIP_CONFIG_SECURE_SESSION_POOL_SIZE - 1;
Optional<SessionHandle> handles[numHandles];
uint16_t sessionIds[numHandles];
for (size_t h = 0; h < numHandles; ++h)
{
constexpr int maxOffset = 5000;
handles[h] = sessionManager.AllocateSession(Transport::SecureSession::Type::kPASE);
handles[h] = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handles[h].HasValue());
sessionIds[h] = handles[h].Value()->AsSecureSession()->GetLocalSessionId();
RandomSessionIdAllocatorOffset(inSuite, sessionManager, maxOffset);
@@ -739,7 +749,9 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext)
// these collide either.
for (int j = 0; j < UINT16_MAX; ++j)
{
auto handle = sessionManager.AllocateSession(Transport::SecureSession::Type::kPASE);
auto handle = sessionManager.AllocateSession(
Transport::SecureSession::Type::kPASE,
ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex));
NL_TEST_ASSERT(inSuite, handle.HasValue());
auto potentialCollision = handle.Value()->AsSecureSession()->GetLocalSessionId();
for (size_t h = 0; h < numHandles; ++h)