blob: 2aca1cdcaf8445f0be2cb86397fce99837f18582 [file] [log] [blame]
/*
*
* Copyright (c) 2020-2021 Project CHIP Authors
* Copyright (c) 2013-2017 Nest Labs, Inc.
* All rights reserved.
*
* 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.
*/
/**
* @file
* This file implements the CHIP Connection object that maintains a UDP connection.
* TODO This class should be extended to support TCP as well...
*
*/
#include "SessionManager.h"
#include <inttypes.h>
#include <string.h>
#include "transport/TraceMessage.h"
#include <app/util/basic-types.h>
#include <credentials/GroupDataProvider.h>
#include <lib/core/CHIPKeyIds.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <protocols/secure_channel/Constants.h>
#include <transport/GroupSession.h>
#include <transport/PairingSession.h>
#include <transport/SecureMessageCodec.h>
#include <transport/TransportMgr.h>
#include <inttypes.h>
namespace chip {
using System::PacketBufferHandle;
using Transport::PeerAddress;
using Transport::SecureSession;
uint32_t EncryptedPacketBufferHandle::GetMessageCounter() const
{
PacketHeader header;
uint16_t headerSize = 0;
CHIP_ERROR err = header.Decode((*this)->Start(), (*this)->DataLength(), &headerSize);
if (err == CHIP_NO_ERROR)
{
return header.GetMessageCounter();
}
ChipLogError(Inet, "Failed to decode EncryptedPacketBufferHandle header with error: %s", ErrorStr(err));
return 0;
}
SessionManager::SessionManager() : mState(State::kNotReady) {}
SessionManager::~SessionManager() {}
CHIP_ERROR SessionManager::Init(System::Layer * systemLayer, TransportMgrBase * transportMgr,
Transport::MessageCounterManagerInterface * messageCounterManager)
{
VerifyOrReturnError(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(transportMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
mState = State::kInitialized;
mSystemLayer = systemLayer;
mTransportMgr = transportMgr;
mMessageCounterManager = messageCounterManager;
// TODO: Handle error from mGlobalEncryptedMessageCounter! Unit tests currently crash if you do!
(void) mGlobalEncryptedMessageCounter.Init();
mGlobalUnencryptedMessageCounter.Init();
ScheduleExpiryTimer();
mTransportMgr->SetSessionManager(this);
return CHIP_NO_ERROR;
}
void SessionManager::Shutdown()
{
CancelExpiryTimer();
mSessionRecoveryDelegates.ReleaseAll();
mMessageCounterManager = nullptr;
mState = State::kNotReady;
mSystemLayer = nullptr;
mTransportMgr = nullptr;
mCB = nullptr;
}
CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, PayloadHeader & payloadHeader,
System::PacketBufferHandle && message, EncryptedPacketBufferHandle & preparedMessage)
{
PacketHeader packetHeader;
if (IsControlMessage(payloadHeader))
{
packetHeader.SetSecureSessionControlMsg(true);
}
#if CHIP_PROGRESS_LOGGING
NodeId destination;
FabricIndex fabricIndex;
#endif // CHIP_PROGRESS_LOGGING
switch (sessionHandle->GetSessionType())
{
case Transport::Session::SessionType::kGroup: {
// TODO : #11911
// For now, just set the packetHeader with the correct data.
packetHeader.SetDestinationGroupId(sessionHandle->AsGroupSession()->GetGroupId());
packetHeader.SetFlags(Header::SecFlagValues::kPrivacyFlag);
packetHeader.SetSessionType(Header::SessionType::kGroupSession);
// TODO : Replace the PeerNodeId with Our nodeId
packetHeader.SetSourceNodeId(kUndefinedNodeId);
if (!packetHeader.IsValidGroupMsg())
{
return CHIP_ERROR_INTERNAL;
}
// Trace before any encryption
CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, message->Start(), message->TotalLength());
// TODO #11911 Update SecureMessageCodec::Encrypt for Group
ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(message));
#if CHIP_PROGRESS_LOGGING
destination = kUndefinedNodeId;
fabricIndex = kUndefinedFabricIndex;
#endif // CHIP_PROGRESS_LOGGING
}
break;
case Transport::Session::SessionType::kSecure: {
SecureSession * session = sessionHandle->AsSecureSession();
if (session == nullptr)
{
return CHIP_ERROR_NOT_CONNECTED;
}
MessageCounter & counter = GetSendCounterForPacket(payloadHeader, *session);
uint32_t messageCounter = counter.Value();
packetHeader
.SetMessageCounter(messageCounter) //
.SetSessionId(session->GetPeerSessionId()) //
.SetSessionType(Header::SessionType::kUnicastSession);
// Trace before any encryption
CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, message->Start(), message->TotalLength());
ReturnErrorOnFailure(SecureMessageCodec::Encrypt(session, payloadHeader, packetHeader, message));
ReturnErrorOnFailure(counter.Advance());
#if CHIP_PROGRESS_LOGGING
destination = session->GetPeerNodeId();
fabricIndex = session->GetFabricIndex();
#endif // CHIP_PROGRESS_LOGGING
}
break;
case Transport::Session::SessionType::kUnauthenticated: {
MessageCounter & counter = mGlobalUnencryptedMessageCounter;
uint32_t messageCounter = counter.Value();
ReturnErrorOnFailure(counter.Advance());
packetHeader.SetMessageCounter(messageCounter);
// Trace after all headers are settled.
CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, message->Start(), message->TotalLength());
ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(message));
#if CHIP_PROGRESS_LOGGING
destination = kUndefinedNodeId;
fabricIndex = kUndefinedFabricIndex;
#endif // CHIP_PROGRESS_LOGGING
}
break;
default:
return CHIP_ERROR_INTERNAL;
}
ChipLogProgress(Inet,
"Prepared %s message %p to 0x" ChipLogFormatX64 " (%u) of type " ChipLogFormatMessageType
" and protocolId " ChipLogFormatProtocolId " on exchange " ChipLogFormatExchangeId
" with MessageCounter:" ChipLogFormatMessageCounter ".",
sessionHandle->GetSessionTypeString(), &preparedMessage, ChipLogValueX64(destination), fabricIndex,
payloadHeader.GetMessageType(), ChipLogValueProtocolId(payloadHeader.GetProtocolID()),
ChipLogValueExchangeIdFromSentHeader(payloadHeader), packetHeader.GetMessageCounter());
ReturnErrorOnFailure(packetHeader.EncodeBeforeData(message));
preparedMessage = EncryptedPacketBufferHandle::MarkEncrypted(std::move(message));
return CHIP_NO_ERROR;
}
CHIP_ERROR SessionManager::SendPreparedMessage(const SessionHandle & sessionHandle,
const EncryptedPacketBufferHandle & preparedMessage)
{
VerifyOrReturnError(mState == State::kInitialized, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(!preparedMessage.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
const Transport::PeerAddress * destination;
switch (sessionHandle->GetSessionType())
{
case Transport::Session::SessionType::kGroup: {
auto groupSession = sessionHandle->AsGroupSession();
Transport::PeerAddress multicastAddress =
Transport::PeerAddress::Multicast(groupSession->GetFabricIndex(), groupSession->GetGroupId());
destination = &multicastAddress; // XXX: this is dangling pointer, must be fixed
char addressStr[Transport::PeerAddress::kMaxToStringSize];
multicastAddress.ToString(addressStr, Transport::PeerAddress::kMaxToStringSize);
ChipLogProgress(Inet,
"Sending %s msg %p with MessageCounter:" ChipLogFormatMessageCounter " to %d"
" at monotonic time: %" PRId64
" msec to Multicast IPV6 address : %s with GroupID of %d and fabric Id of %d",
"encrypted", &preparedMessage, preparedMessage.GetMessageCounter(), groupSession->GetGroupId(),
System::SystemClock().GetMonotonicMilliseconds64().count(), addressStr, groupSession->GetGroupId(),
groupSession->GetFabricIndex());
}
break;
case Transport::Session::SessionType::kSecure: {
// Find an active connection to the specified peer node
SecureSession * secure = sessionHandle->AsSecureSession();
// This marks any connection where we send data to as 'active'
secure->MarkActive();
destination = &secure->GetPeerAddress();
ChipLogProgress(Inet,
"Sending %s msg %p with MessageCounter:" ChipLogFormatMessageCounter " to 0x" ChipLogFormatX64
" (%u) at monotonic time: %" PRId64 " msec",
"encrypted", &preparedMessage, preparedMessage.GetMessageCounter(),
ChipLogValueX64(secure->GetPeerNodeId()), secure->GetFabricIndex(),
System::SystemClock().GetMonotonicMilliseconds64().count());
}
break;
case Transport::Session::SessionType::kUnauthenticated: {
auto unauthenticated = sessionHandle->AsUnauthenticatedSession();
unauthenticated->MarkActive();
destination = &unauthenticated->GetPeerAddress();
ChipLogProgress(Inet,
"Sending %s msg %p with MessageCounter:" ChipLogFormatMessageCounter " to 0x" ChipLogFormatX64
" at monotonic time: %" PRId64 " msec",
sessionHandle->GetSessionTypeString(), &preparedMessage, preparedMessage.GetMessageCounter(),
ChipLogValueX64(kUndefinedNodeId), System::SystemClock().GetMonotonicMilliseconds64().count());
}
break;
default:
return CHIP_ERROR_INTERNAL;
}
PacketBufferHandle msgBuf = preparedMessage.CastToWritable();
VerifyOrReturnError(!msgBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(!msgBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
if (mTransportMgr != nullptr)
{
return mTransportMgr->SendMessage(*destination, std::move(msgBuf));
}
else
{
ChipLogError(Inet, "The transport manager is not initialized. Unable to send the message");
return CHIP_ERROR_INCORRECT_STATE;
}
}
void SessionManager::ExpirePairing(const SessionHandle & sessionHandle)
{
mSecureSessions.ReleaseSession(sessionHandle->AsSecureSession());
}
void SessionManager::ExpireAllPairings(NodeId peerNodeId, FabricIndex fabric)
{
mSecureSessions.ForEachSession([&](auto session) {
if (session->GetPeerNodeId() == peerNodeId && session->GetFabricIndex() == fabric)
{
mSecureSessions.ReleaseSession(session);
}
return Loop::Continue;
});
}
void SessionManager::ExpireAllPairingsForFabric(FabricIndex fabric)
{
ChipLogDetail(Inet, "Expiring all connections for fabric %d!!", fabric);
mSecureSessions.ForEachSession([&](auto session) {
if (session->GetFabricIndex() == fabric)
{
mSecureSessions.ReleaseSession(session);
}
return Loop::Continue;
});
}
CHIP_ERROR SessionManager::NewPairing(SessionHolder & sessionHolder, const Optional<Transport::PeerAddress> & peerAddr,
NodeId peerNodeId, PairingSession * pairing, CryptoContext::SessionRole direction,
FabricIndex fabric)
{
uint16_t peerSessionId = pairing->GetPeerSessionId();
uint16_t localSessionId = pairing->GetLocalSessionId();
Optional<SessionHandle> session = mSecureSessions.FindSecureSessionByLocalKey(localSessionId);
// Find any existing connection with the same local key ID
if (session.HasValue())
{
mSecureSessions.ReleaseSession(session.Value()->AsSecureSession());
}
ChipLogDetail(Inet, "New secure session created for device 0x" ChipLogFormatX64 ", LSID:%d PSID:%d!",
ChipLogValueX64(peerNodeId), localSessionId, peerSessionId);
session = mSecureSessions.CreateNewSecureSession(pairing->GetSecureSessionType(), localSessionId, peerNodeId,
pairing->GetPeerCATs(), peerSessionId, fabric, pairing->GetMRPConfig());
ReturnErrorCodeIf(!session.HasValue(), CHIP_ERROR_NO_MEMORY);
Transport::SecureSession * secureSession = session.Value()->AsSecureSession();
if (peerAddr.HasValue() && peerAddr.Value().GetIPAddress() != Inet::IPAddress::Any)
{
secureSession->SetPeerAddress(peerAddr.Value());
}
else if (peerAddr.HasValue() && peerAddr.Value().GetTransportType() == Transport::Type::kBle)
{
secureSession->SetPeerAddress(peerAddr.Value());
}
else if (peerAddr.HasValue() &&
(peerAddr.Value().GetTransportType() == Transport::Type::kTcp ||
peerAddr.Value().GetTransportType() == Transport::Type::kUdp))
{
return CHIP_ERROR_INVALID_ARGUMENT;
}
ReturnErrorOnFailure(pairing->DeriveSecureSession(secureSession->GetCryptoContext(), direction));
secureSession->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(pairing->GetPeerCounter());
sessionHolder.Grab(session.Value());
return CHIP_NO_ERROR;
}
void SessionManager::ScheduleExpiryTimer()
{
CHIP_ERROR err = mSystemLayer->StartTimer(System::Clock::Milliseconds32(CHIP_PEER_CONNECTION_TIMEOUT_CHECK_FREQUENCY_MS),
SessionManager::ExpiryTimerCallback, this);
VerifyOrDie(err == CHIP_NO_ERROR);
}
void SessionManager::CancelExpiryTimer()
{
if (mSystemLayer != nullptr)
{
mSystemLayer->CancelTimer(SessionManager::ExpiryTimerCallback, this);
}
}
void SessionManager::OnMessageReceived(const PeerAddress & peerAddress, System::PacketBufferHandle && msg)
{
PacketHeader packetHeader;
ReturnOnFailure(packetHeader.DecodeAndConsume(msg));
if (packetHeader.IsEncrypted())
{
if (packetHeader.IsGroupSession())
{
SecureGroupMessageDispatch(packetHeader, peerAddress, std::move(msg));
}
else
{
SecureUnicastMessageDispatch(packetHeader, peerAddress, std::move(msg));
}
}
else
{
MessageDispatch(packetHeader, peerAddress, std::move(msg));
}
}
void SessionManager::RegisterRecoveryDelegate(SessionRecoveryDelegate & cb)
{
#ifndef NDEBUG
mSessionRecoveryDelegates.ForEachActiveObject([&](std::reference_wrapper<SessionRecoveryDelegate> * i) {
VerifyOrDie(std::addressof(cb) != std::addressof(i->get()));
return Loop::Continue;
});
#endif
std::reference_wrapper<SessionRecoveryDelegate> * slot = mSessionRecoveryDelegates.CreateObject(cb);
VerifyOrDie(slot != nullptr);
}
void SessionManager::UnregisterRecoveryDelegate(SessionRecoveryDelegate & cb)
{
mSessionRecoveryDelegates.ForEachActiveObject([&](std::reference_wrapper<SessionRecoveryDelegate> * i) {
if (std::addressof(cb) == std::addressof(i->get()))
{
mSessionRecoveryDelegates.ReleaseObject(i);
return Loop::Break;
}
return Loop::Continue;
});
}
void SessionManager::RefreshSessionOperationalData(const SessionHandle & sessionHandle)
{
mSessionRecoveryDelegates.ForEachActiveObject([&](std::reference_wrapper<SessionRecoveryDelegate> * cb) {
cb->get().OnFirstMessageDeliveryFailed(sessionHandle);
return Loop::Continue;
});
}
void SessionManager::MessageDispatch(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
System::PacketBufferHandle && msg)
{
Optional<SessionHandle> optionalSession = mUnauthenticatedSessions.FindOrAllocateEntry(peerAddress, gDefaultMRPConfig);
if (!optionalSession.HasValue())
{
ChipLogError(Inet, "UnauthenticatedSession exhausted");
return;
}
const SessionHandle & session = optionalSession.Value();
Transport::UnauthenticatedSession * unsecuredSession = session->AsUnauthenticatedSession();
SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;
// Verify message counter
CHIP_ERROR err = unsecuredSession->GetPeerMessageCounter().VerifyOrTrustFirst(packetHeader.GetMessageCounter());
if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
{
isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
err = CHIP_NO_ERROR;
}
VerifyOrDie(err == CHIP_NO_ERROR);
unsecuredSession->MarkActive();
PayloadHeader payloadHeader;
ReturnOnFailure(payloadHeader.DecodeAndConsume(msg));
if (isDuplicate == SessionMessageDelegate::DuplicateMessage::Yes)
{
ChipLogDetail(Inet,
"Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
" on exchange " ChipLogFormatExchangeId,
packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
}
unsecuredSession->GetPeerMessageCounter().Commit(packetHeader.GetMessageCounter());
if (mCB != nullptr)
{
CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, unsecuredSession, peerAddress, msg->Start(), msg->TotalLength());
mCB->OnMessageReceived(packetHeader, payloadHeader, session, peerAddress, isDuplicate, std::move(msg));
}
}
void SessionManager::SecureUnicastMessageDispatch(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
System::PacketBufferHandle && msg)
{
CHIP_ERROR err = CHIP_NO_ERROR;
Optional<SessionHandle> session = mSecureSessions.FindSecureSessionByLocalKey(packetHeader.GetSessionId());
PayloadHeader payloadHeader;
SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;
if (msg.IsNull())
{
ChipLogError(Inet, "Secure transport received Unicast NULL packet, discarding");
return;
}
if (!session.HasValue())
{
ChipLogError(Inet, "Data received on an unknown session (LSID=%d). Dropping it!", packetHeader.GetSessionId());
return;
}
Transport::SecureSession * secureSession = session.Value()->AsSecureSession();
// Decrypt and verify the message before message counter verification or any further processing.
if (SecureMessageCodec::Decrypt(secureSession, payloadHeader, packetHeader, msg) != CHIP_NO_ERROR)
{
ChipLogError(Inet, "Secure transport received message, but failed to decode/authenticate it, discarding");
return;
}
err = secureSession->GetSessionMessageCounter().GetPeerMessageCounter().Verify(packetHeader.GetMessageCounter());
if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
{
isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
err = CHIP_NO_ERROR;
}
if (err != CHIP_NO_ERROR)
{
ChipLogError(Inet, "Message counter verify failed, err = %" CHIP_ERROR_FORMAT, err.Format());
return;
}
secureSession->MarkActive();
if (isDuplicate == SessionMessageDelegate::DuplicateMessage::Yes && !payloadHeader.NeedsAck())
{
ChipLogDetail(Inet,
"Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
" on exchange " ChipLogFormatExchangeId,
packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
if (!payloadHeader.NeedsAck())
{
// If it's a duplicate message, but doesn't require an ack, let's drop it right here to save CPU
// cycles on further message processing.
return;
}
}
secureSession->GetSessionMessageCounter().GetPeerMessageCounter().Commit(packetHeader.GetMessageCounter());
// TODO: once mDNS address resolution is available reconsider if this is required
// This updates the peer address once a packet is received from a new address
// and serves as a way to auto-detect peer changing IPs.
if (secureSession->GetPeerAddress() != peerAddress)
{
secureSession->SetPeerAddress(peerAddress);
}
if (mCB != nullptr)
{
CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, secureSession, peerAddress, msg->Start(), msg->TotalLength());
mCB->OnMessageReceived(packetHeader, payloadHeader, session.Value(), peerAddress, isDuplicate, std::move(msg));
}
}
void SessionManager::SecureGroupMessageDispatch(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
System::PacketBufferHandle && msg)
{
PayloadHeader payloadHeader;
SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;
// Credentials::GroupDataProvider * groups = Credentials::GetGroupDataProvider();
if (!packetHeader.GetDestinationGroupId().HasValue())
{
return; // malformed packet
}
if (msg.IsNull())
{
ChipLogError(Inet, "Secure transport received Groupcast NULL packet, discarding");
return;
}
// Check if Message Header is valid first
if (!(packetHeader.IsValidMCSPMsg() || packetHeader.IsValidGroupMsg()))
{
ChipLogError(Inet, "Invalid condition found in packet header");
return;
}
// Trial decryption with GroupDataProvider. TODO: Implement the GroupDataProvider Class
// TODO retrieve also the fabricIndex with the GroupDataProvider.
// VerifyOrExit(CHIP_NO_ERROR == groups->DecryptMessage(packetHeader, payloadHeader, msg),
// ChipLogError(Inet, "Secure transport received group message, but failed to decode it, discarding"));
ReturnOnFailure(payloadHeader.DecodeAndConsume(msg));
// MCSP check
if (packetHeader.IsValidMCSPMsg())
{
// TODO
// if (packetHeader.GetDestinationNodeId().Value() == ThisDeviceNodeID)
// {
// MCSP processing..
// }
return;
}
// Group Messages should never send an Ack
if (payloadHeader.NeedsAck())
{
ChipLogError(Inet, "Unexpected ACK requested for group message");
return;
}
// TODO: Handle Group message counter here spec 4.7.3
// spec 4.5.1.2 for msg counter
if (isDuplicate == SessionMessageDelegate::DuplicateMessage::Yes)
{
ChipLogDetail(Inet,
"Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
" on exchange " ChipLogFormatExchangeId,
packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
// If it's a duplicate message, let's drop it right here to save CPU cycles
return;
}
// TODO: Commit Group Message Counter
if (mCB != nullptr)
{
Optional<SessionHandle> session = CreateGroupSession(packetHeader.GetDestinationGroupId().Value());
VerifyOrReturn(session.HasValue(), ChipLogError(Inet, "Error when creating group session handle."));
Transport::GroupSession * groupSession = session.Value()->AsGroupSession();
CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, groupSession, peerAddress, msg->Start(), msg->TotalLength());
mCB->OnMessageReceived(packetHeader, payloadHeader, session.Value(), peerAddress, isDuplicate, std::move(msg));
RemoveGroupSession(groupSession);
}
}
void SessionManager::ExpiryTimerCallback(System::Layer * layer, void * param)
{
SessionManager * mgr = reinterpret_cast<SessionManager *>(param);
#if CHIP_CONFIG_SESSION_REKEYING
// TODO(#2279): session expiration is currently disabled until rekeying is supported
// the #ifdef should be removed after that.
mgr->mSecureSessions.ExpireInactiveSessions(System::SystemClock().GetMonotonicTimestamp(),
System::Clock::Milliseconds32(CHIP_PEER_CONNECTION_TIMEOUT_MS));
#endif
mgr->ScheduleExpiryTimer(); // re-schedule the oneshot timer
}
SessionHandle SessionManager::FindSecureSessionForNode(NodeId peerNodeId)
{
SecureSession * found = nullptr;
mSecureSessions.ForEachSession([&](auto session) {
if (session->GetPeerNodeId() == peerNodeId)
{
found = session;
return Loop::Break;
}
return Loop::Continue;
});
VerifyOrDie(found != nullptr);
return SessionHandle(*found);
}
/**
* Provides a means to get diagnostic information such as number of sessions.
*/
[[maybe_unused]] CHIP_ERROR SessionManager::ForEachSessionHandle(void * context, SessionHandleCallback lambda)
{
mSecureSessions.ForEachSession([&](auto session) {
SessionHandle handle(*session);
lambda(context, handle);
return Loop::Continue;
});
return CHIP_NO_ERROR;
}
} // namespace chip