Skip to content

Commit

Permalink
[app] decouple CASESession from OperationalDevice (#12148)
Browse files Browse the repository at this point in the history
* [app] decouple CASESession from OperationalDevice

* [app] make size of CASE client and device pool configurable
  • Loading branch information
gjc13 authored and pull[bot] committed Jan 26, 2022
1 parent f8ee6df commit 1022c3b
Show file tree
Hide file tree
Showing 12 changed files with 409 additions and 79 deletions.
4 changes: 4 additions & 0 deletions src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ static_library("app") {
"AttributePathExpandIterator.h",
"AttributePathParams.h",
"BufferedReadCallback.cpp",
"CASEClient.cpp",
"CASEClient.h",
"CASEClientPool.h",
"CASESessionManager.cpp",
"CASESessionManager.h",
"Command.cpp",
Expand Down Expand Up @@ -121,6 +124,7 @@ static_library("app") {
"MessageDef/WriteResponseMessage.cpp",
"OperationalDeviceProxy.cpp",
"OperationalDeviceProxy.h",
"OperationalDeviceProxyPool.h",
"ReadClient.cpp",
"ReadHandler.cpp",
"StatusResponse.cpp",
Expand Down
92 changes: 92 additions & 0 deletions src/app/CASEClient.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
*
* 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.
*/

#include <app/CASEClient.h>

namespace chip {

CASEClient::CASEClient(const CASEClientInitParams & params) : mInitParams(params) {}

void CASEClient::SetMRPIntervals(const ReliableMessageProtocolConfig & mrpConfig)
{
mCASESession.SetMRPConfig(mrpConfig);
}

CHIP_ERROR CASEClient::EstablishSession(PeerId peer, const Transport::PeerAddress & peerAddress,
const ReliableMessageProtocolConfig & mrpConfig, OnCASEConnected onConnection,
OnCASEConnectionFailure onFailure, void * context)
{
// Create a UnauthenticatedSession for CASE pairing.
// Don't use mSecureSession here, because mSecureSession is for encrypted communication.
Optional<SessionHandle> session = mInitParams.sessionManager->CreateUnauthenticatedSession(peerAddress, mrpConfig);
VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);

Messaging::ExchangeContext * exchange = mInitParams.exchangeMgr->NewContext(session.Value(), &mCASESession);
VerifyOrReturnError(exchange != nullptr, CHIP_ERROR_INTERNAL);

ReturnErrorOnFailure(mCASESession.MessageDispatch().Init(mInitParams.sessionManager));

uint16_t keyID = 0;
ReturnErrorOnFailure(mInitParams.idAllocator->Allocate(keyID));

ReturnErrorOnFailure(
mCASESession.EstablishSession(peerAddress, mInitParams.fabricInfo, peer.GetNodeId(), keyID, exchange, this));
mConnectionSuccessCallback = onConnection;
mConnectionFailureCallback = onFailure;
mConectionContext = context;
mPeerId = peer;
mPeerAddress = peerAddress;

return CHIP_NO_ERROR;
}

void CASEClient::OnSessionEstablishmentError(CHIP_ERROR error)
{
mInitParams.idAllocator->Free(mCASESession.GetLocalSessionId());

if (mConnectionFailureCallback)
{
mConnectionFailureCallback(mConectionContext, this, error);
}
}

void CASEClient::OnSessionEstablished()
{
// On successfull CASE connection, the local session ID will be used for the derived secure session.
if (mConnectionSuccessCallback)
{
mConnectionSuccessCallback(mConectionContext, this);
}
}

CHIP_ERROR CASEClient::DeriveSecureSessionHandle(Optional<SessionHandle> & handle)
{
CHIP_ERROR err = mInitParams.sessionManager->NewPairing(
Optional<Transport::PeerAddress>::Value(mPeerAddress), mPeerId.GetNodeId(), &mCASESession,
CryptoContext::SessionRole::kInitiator, mInitParams.fabricInfo->GetFabricIndex());
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed in setting up CASE secure channel: err %s", ErrorStr(err));
return err;
}
handle.SetValue(SessionHandle(mPeerId.GetNodeId(), mCASESession.GetLocalSessionId(), mCASESession.GetPeerSessionId(),
mInitParams.fabricInfo->GetFabricIndex()));

return CHIP_NO_ERROR;
}

}; // namespace chip
70 changes: 70 additions & 0 deletions src/app/CASEClient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
*
* 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 <messaging/ExchangeMgr.h>
#include <messaging/ReliableMessageProtocolConfig.h>
#include <protocols/secure_channel/CASESession.h>
#include <protocols/secure_channel/SessionIDAllocator.h>

namespace chip {

class CASEClient;

typedef void (*OnCASEConnected)(void * context, CASEClient * client);
typedef void (*OnCASEConnectionFailure)(void * context, CASEClient * client, CHIP_ERROR error);

struct CASEClientInitParams
{
SessionManager * sessionManager = nullptr;
Messaging::ExchangeManager * exchangeMgr = nullptr;
SessionIDAllocator * idAllocator = nullptr;
FabricInfo * fabricInfo = nullptr;
};

class DLL_EXPORT CASEClient : public SessionEstablishmentDelegate
{
public:
CASEClient(const CASEClientInitParams & params);

void SetMRPIntervals(const ReliableMessageProtocolConfig & mrpConfig);

CHIP_ERROR EstablishSession(PeerId peer, const Transport::PeerAddress & peerAddress,
const ReliableMessageProtocolConfig & mrpConfig, OnCASEConnected onConnection,
OnCASEConnectionFailure onFailure, void * context);

// Implementation of SessionEstablishmentDelegate
void OnSessionEstablishmentError(CHIP_ERROR error) override;

void OnSessionEstablished() override;

CHIP_ERROR DeriveSecureSessionHandle(Optional<SessionHandle> & handle);

private:
CASEClientInitParams mInitParams;

CASESession mCASESession;
PeerId mPeerId;
Transport::PeerAddress mPeerAddress;

OnCASEConnected mConnectionSuccessCallback = nullptr;
OnCASEConnectionFailure mConnectionFailureCallback = nullptr;
void * mConectionContext = nullptr;
};

} // namespace chip
47 changes: 47 additions & 0 deletions src/app/CASEClientPool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
*
* 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 <app/CASEClient.h>
#include <lib/support/Pool.h>

namespace chip {

class CASEClientPoolDelegate
{
public:
virtual CASEClient * Allocate(CASEClientInitParams params) = 0;

virtual void Release(CASEClient * client) = 0;

virtual ~CASEClientPoolDelegate() {}
};

template <size_t N>
class CASEClientPool : public CASEClientPoolDelegate
{
public:
CASEClient * Allocate(CASEClientInitParams params) override { return mClientPool.CreateObject(params); }

void Release(CASEClient * client) override { mClientPool.ReleaseObject(client); }

private:
BitMapObjectPool<CASEClient, N, OnObjectPoolDestruction::IgnoreUnsafeDoNotUseInNewCode> mClientPool;
};

}; // namespace chip
30 changes: 5 additions & 25 deletions src/app/CASESessionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ CHIP_ERROR CASESessionManager::FindOrEstablishSession(NodeId nodeId, Callback::C
// TODO - Implement LRU to evict least recently used session to handle mActiveSessions pool exhaustion
if (nodeIDWasResolved)
{
session = mActiveSessions.CreateObject(mConfig.sessionInitParams, peerId, resolutionData);
session = mConfig.devicePool->Allocate(mConfig.sessionInitParams, peerId, resolutionData);
}
else
{
session = mActiveSessions.CreateObject(mConfig.sessionInitParams, peerId);
session = mConfig.devicePool->Allocate(mConfig.sessionInitParams, peerId);
}

if (session == nullptr)
Expand Down Expand Up @@ -120,39 +120,19 @@ void CASESessionManager::OnSessionReleased(SessionHandle sessionHandle)

OperationalDeviceProxy * CASESessionManager::FindSession(SessionHandle session)
{
OperationalDeviceProxy * foundSession = nullptr;
mActiveSessions.ForEachActiveObject([&](auto * activeSession) {
if (activeSession->MatchesSession(session))
{
foundSession = activeSession;
return Loop::Break;
}
return Loop::Continue;
});

return foundSession;
return mConfig.devicePool->FindDevice(session);
}

OperationalDeviceProxy * CASESessionManager::FindExistingSession(NodeId id)
{
OperationalDeviceProxy * foundSession = nullptr;
mActiveSessions.ForEachActiveObject([&](auto * activeSession) {
if (activeSession->GetDeviceId() == id)
{
foundSession = activeSession;
return Loop::Break;
}
return Loop::Continue;
});

return foundSession;
return mConfig.devicePool->FindDevice(id);
}

void CASESessionManager::ReleaseSession(OperationalDeviceProxy * session)
{
if (session != nullptr)
{
mActiveSessions.ReleaseObject(session);
mConfig.devicePool->Release(session);
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/app/CASESessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

#pragma once

#include <app/CASEClientPool.h>
#include <app/OperationalDeviceProxy.h>
#include <app/OperationalDeviceProxyPool.h>
#include <lib/core/CHIPConfig.h>
#include <lib/core/CHIPCore.h>
#include <lib/dnssd/DnssdCache.h>
Expand All @@ -33,6 +35,7 @@ struct CASESessionManagerConfig
{
DeviceProxyInitParams sessionInitParams;
Dnssd::DnssdCache<CHIP_CONFIG_MDNS_CACHE_SIZE> * dnsCache = nullptr;
OperationalDeviceProxyPoolDelegate * devicePool = nullptr;
};

/**
Expand All @@ -50,7 +53,7 @@ class CASESessionManager : public SessionReleaseDelegate, public Dnssd::Resolver

CASESessionManager(CASESessionManagerConfig & params)
{
VerifyOrReturn(params.sessionInitParams.Validate() == CHIP_NO_ERROR);
VerifyOrDie(params.sessionInitParams.Validate() == CHIP_NO_ERROR);

mConfig = params;
}
Expand Down Expand Up @@ -103,10 +106,6 @@ class CASESessionManager : public SessionReleaseDelegate, public Dnssd::Resolver
OperationalDeviceProxy * FindSession(SessionHandle session);
void ReleaseSession(OperationalDeviceProxy * device);

BitMapObjectPool<OperationalDeviceProxy, CHIP_CONFIG_CONTROLLER_MAX_ACTIVE_DEVICES,
OnObjectPoolDestruction::IgnoreUnsafeDoNotUseInNewCode>
mActiveSessions;

CASESessionManagerConfig mConfig;
};

Expand Down
Loading

0 comments on commit 1022c3b

Please sign in to comment.