Clarify CASE session establishment API error reporting. (#18569)
* Clarify CASE session establishment API error reporting.
Consumers were very unclear on the fact that in sync-error cases we
would both return error _and_ call the error callback, leading some of
them to mis-handle the error processing. For example, the OTA
requestor code would double-notify its consumer on errors.
This PR on its own does not entirely fix that, but makes the API
contract a lot clearer.
Change details:
* The confusingly named Initialized state of OperationalDeviceProxy
has been renamed to HasAddress.
* The new ResolvingAddress state for OperationalDeviceProxy is to
allow the "destroy the OperationalDeviceProxy if it's not going to
be successful" cleanup logic in
CASESessionManager::FindOrEstablishSession to keep working.
* The change to grab the peer adddress in
OperationalDeviceProxy::AttachToExistingSecureSession is fixing a
pre-existing problem, where we could end up not setting the address
there, then get the session evicted and end up in our "has address,
need to establish session next" state but without an actual address.
* Various unused APIs that date back to a quite different
OperationalDeviceProxy setup, with an address cache involved, were
removed.
* In CASESessionManager::FindOrEstablishSession the out-of-memory case
was violating the API contract, which allows passing in null
callbacks; it would crash in that case.
* Fix tv examples.
* Address review comments.
diff --git a/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.cpp b/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.cpp
index a3b1001..c886c04 100644
--- a/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.cpp
+++ b/examples/tv-casting-app/tv-casting-common/commands/clusters/ModelCommand.cpp
@@ -56,8 +56,9 @@
}
PeerId peerID = fabric->GetPeerIdForNode(mNodeId);
- return server->GetCASESessionManager()->FindOrEstablishSession(peerID, &mOnDeviceConnectedCallback,
- &mOnDeviceConnectionFailureCallback);
+ server->GetCASESessionManager()->FindOrEstablishSession(peerID, &mOnDeviceConnectedCallback,
+ &mOnDeviceConnectionFailureCallback);
+ return CHIP_NO_ERROR;
}
void ModelCommand::OnDeviceConnectedFn(void * context, OperationalDeviceProxy * device)
diff --git a/examples/tv-casting-app/tv-casting-common/src/TargetVideoPlayerInfo.cpp b/examples/tv-casting-app/tv-casting-common/src/TargetVideoPlayerInfo.cpp
index f53db90..4d49a64 100644
--- a/examples/tv-casting-app/tv-casting-common/src/TargetVideoPlayerInfo.cpp
+++ b/examples/tv-casting-app/tv-casting-common/src/TargetVideoPlayerInfo.cpp
@@ -42,13 +42,7 @@
PeerId peerID = fabric->GetPeerIdForNode(nodeId);
- CHIP_ERROR err =
- server->GetCASESessionManager()->FindOrEstablishSession(peerID, &mOnConnectedCallback, &mOnConnectionFailureCallback);
- if (err != CHIP_NO_ERROR)
- {
- ChipLogError(AppServer, "Could not establish a session to the peer");
- return err;
- }
+ server->GetCASESessionManager()->FindOrEstablishSession(peerID, &mOnConnectedCallback, &mOnConnectionFailureCallback);
if (mOperationalDeviceProxy == nullptr)
{
diff --git a/src/app/CASESessionManager.cpp b/src/app/CASESessionManager.cpp
index 6af089c..24fd9ed 100644
--- a/src/app/CASESessionManager.cpp
+++ b/src/app/CASESessionManager.cpp
@@ -28,8 +28,8 @@
return AddressResolve::Resolver::Instance().Init(systemLayer);
}
-CHIP_ERROR CASESessionManager::FindOrEstablishSession(PeerId peerId, Callback::Callback<OnDeviceConnected> * onConnection,
- Callback::Callback<OnDeviceConnectionFailure> * onFailure)
+void CASESessionManager::FindOrEstablishSession(PeerId peerId, Callback::Callback<OnDeviceConnected> * onConnection,
+ Callback::Callback<OnDeviceConnectionFailure> * onFailure)
{
ChipLogDetail(CASESessionManager, "FindOrEstablishSession: PeerId = " ChipLogFormatX64 ":" ChipLogFormatX64,
ChipLogValueX64(peerId.GetCompressedFabricId()), ChipLogValueX64(peerId.GetNodeId()));
@@ -43,19 +43,25 @@
if (session == nullptr)
{
- onFailure->mCall(onFailure->mContext, peerId, CHIP_ERROR_NO_MEMORY);
- return CHIP_ERROR_NO_MEMORY;
+ if (onFailure != nullptr)
+ {
+ onFailure->mCall(onFailure->mContext, peerId, CHIP_ERROR_NO_MEMORY);
+ }
+ return;
}
}
- CHIP_ERROR err = session->Connect(onConnection, onFailure);
- if (err != CHIP_NO_ERROR)
+ session->Connect(onConnection, onFailure);
+ if (!session->IsConnected() && !session->IsConnecting() && !session->IsResolvingAddress())
{
- // Release the peer rather than the pointer in case the failure handler has already released the session.
+ // This session is not making progress toward anything. It will have
+ // notified the consumer about the failure already via the provided
+ // callbacks, if any.
+ //
+ // Release the peer rather than the pointer in case the failure handler
+ // has already released the session.
ReleaseSession(peerId);
}
-
- return err;
}
void CASESessionManager::ReleaseSession(PeerId peerId)
diff --git a/src/app/CASESessionManager.h b/src/app/CASESessionManager.h
index 32e5004..a464a40 100644
--- a/src/app/CASESessionManager.h
+++ b/src/app/CASESessionManager.h
@@ -55,13 +55,21 @@
void Shutdown() {}
/**
- * Find an existing session for the given node ID, or trigger a new session request.
- * The caller can optionally provide `onConnection` and `onFailure` callback objects. If provided,
- * these will be used to inform the caller about successful or failed connection establishment.
- * If the connection is already established, the `onConnection` callback will be immediately called.
+ * Find an existing session for the given node ID, or trigger a new session
+ * request.
+ *
+ * The caller can optionally provide `onConnection` and `onFailure` callback
+ * objects. If provided, these will be used to inform the caller about
+ * successful or failed connection establishment.
+ *
+ * If the connection is already established, the `onConnection` callback
+ * will be immediately called, before FindOrEstablishSession returns.
+ *
+ * The `onFailure` callback may be called before the FindOrEstablishSession
+ * call returns, for error cases that are detected synchronously.
*/
- CHIP_ERROR FindOrEstablishSession(PeerId peerId, Callback::Callback<OnDeviceConnected> * onConnection,
- Callback::Callback<OnDeviceConnectionFailure> * onFailure);
+ void FindOrEstablishSession(PeerId peerId, Callback::Callback<OnDeviceConnected> * onConnection,
+ Callback::Callback<OnDeviceConnectionFailure> * onFailure);
OperationalDeviceProxy * FindExistingSession(PeerId peerId) const;
diff --git a/src/app/OperationalDeviceProxy.cpp b/src/app/OperationalDeviceProxy.cpp
index 51f3afe..55d78fa 100644
--- a/src/app/OperationalDeviceProxy.cpp
+++ b/src/app/OperationalDeviceProxy.cpp
@@ -65,7 +65,7 @@
bool OperationalDeviceProxy::AttachToExistingSecureSession()
{
- VerifyOrReturnError(mState == State::NeedsAddress || mState == State::Initialized, false);
+ VerifyOrReturnError(mState == State::NeedsAddress || mState == State::ResolvingAddress || mState == State::HasAddress, false);
ScopedNodeId peerNodeId(mPeerId.GetNodeId(), mFabricInfo->GetFabricIndex());
auto sessionHandle =
@@ -74,6 +74,7 @@
{
ChipLogProgress(Controller, "Found an existing secure session to [" ChipLogFormatX64 "-" ChipLogFormatX64 "]!",
ChipLogValueX64(mPeerId.GetCompressedFabricId()), ChipLogValueX64(mPeerId.GetNodeId()));
+ mDeviceAddress = sessionHandle.Value()->AsSecureSession()->GetPeerAddress();
mSecureSession.Grab(sessionHandle.Value());
return true;
}
@@ -81,8 +82,8 @@
return false;
}
-CHIP_ERROR OperationalDeviceProxy::Connect(Callback::Callback<OnDeviceConnected> * onConnection,
- Callback::Callback<OnDeviceConnectionFailure> * onFailure)
+void OperationalDeviceProxy::Connect(Callback::Callback<OnDeviceConnected> * onConnection,
+ Callback::Callback<OnDeviceConnectionFailure> * onFailure)
{
CHIP_ERROR err = CHIP_NO_ERROR;
bool isConnected = false;
@@ -104,12 +105,25 @@
isConnected = AttachToExistingSecureSession();
if (!isConnected)
{
+ // LookupPeerAddress could perhaps call back with a result
+ // synchronously, so do our state update first.
+ MoveToState(State::ResolvingAddress);
err = LookupPeerAddress();
+ if (err != CHIP_NO_ERROR)
+ {
+ // Roll back the state change, since we are presumably not in
+ // the middle of a lookup.
+ MoveToState(State::NeedsAddress);
+ }
}
break;
- case State::Initialized:
+ case State::ResolvingAddress:
+ isConnected = AttachToExistingSecureSession();
+ break;
+
+ case State::HasAddress:
isConnected = AttachToExistingSecureSession();
if (!isConnected)
{
@@ -143,14 +157,14 @@
{
DequeueConnectionCallbacks(err);
}
-
- return err;
}
-CHIP_ERROR OperationalDeviceProxy::UpdateDeviceData(const Transport::PeerAddress & addr,
- const ReliableMessageProtocolConfig & config)
+void OperationalDeviceProxy::UpdateDeviceData(const Transport::PeerAddress & addr, const ReliableMessageProtocolConfig & config)
{
- VerifyOrReturnLogError(mState != State::Uninitialized, CHIP_ERROR_INCORRECT_STATE);
+ if (mState == State::Uninitialized)
+ {
+ return;
+ }
#if CHIP_DETAIL_LOGGING
char peerAddrBuff[Transport::PeerAddress::kMaxToStringSize];
@@ -171,9 +185,9 @@
mCASEClient->SetRemoteMRPIntervals(mRemoteMRPConfig);
}
- if (mState == State::NeedsAddress)
+ if (mState == State::ResolvingAddress)
{
- MoveToState(State::Initialized);
+ MoveToState(State::HasAddress);
err = EstablishConnection();
if (err != CHIP_NO_ERROR)
{
@@ -185,16 +199,14 @@
if (!mSecureSession)
{
// Nothing needs to be done here. It's not an error to not have a
- // secureSession. For one thing, we could have gotten an different
+ // secureSession. For one thing, we could have gotten a different
// UpdateAddress already and that caused connections to be torn down and
// whatnot.
- return CHIP_NO_ERROR;
+ return;
}
mSecureSession.Get().Value()->AsSecureSession()->SetPeerAddress(addr);
}
-
- return err;
}
CHIP_ERROR OperationalDeviceProxy::EstablishConnection()
@@ -281,7 +293,7 @@
// was just CASE connection failure. So let's re-use the cached address to re-do CASE again
// if need-be.
//
- MoveToState(State::Initialized);
+ MoveToState(State::HasAddress);
DequeueConnectionCallbacks(error);
@@ -307,17 +319,11 @@
{
mInitParams.sessionManager->ExpirePairing(mSecureSession.Get().Value());
}
- MoveToState(State::Initialized);
+ MoveToState(State::HasAddress);
return CHIP_NO_ERROR;
}
-void OperationalDeviceProxy::Clear()
-{
- MoveToState(State::Uninitialized);
- mInitParams = DeviceProxyInitParams();
-}
-
void OperationalDeviceProxy::CleanupCASEClient()
{
if (mCASEClient)
@@ -329,7 +335,7 @@
void OperationalDeviceProxy::OnSessionReleased()
{
- MoveToState(State::Initialized);
+ MoveToState(State::HasAddress);
}
CHIP_ERROR OperationalDeviceProxy::ShutdownSubscriptions()
@@ -361,6 +367,9 @@
CHIP_ERROR OperationalDeviceProxy::LookupPeerAddress()
{
+ // NOTE: This is public API that can be used to update our stored peer
+ // address even when we are in State::Connected, so we do not make any
+ // MoveToState calls in this method.
if (mAddressLookupHandle.IsActive())
{
ChipLogProgress(Discovery, "Operational node lookup already in progress. Will NOT start a new one.");
@@ -382,6 +391,11 @@
ChipLogError(Discovery, "Operational discovery failed for 0x" ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT,
ChipLogValueX64(peerId.GetNodeId()), reason.Format());
+ if (IsResolvingAddress())
+ {
+ MoveToState(State::NeedsAddress);
+ }
+
DequeueConnectionCallbacks(reason);
}
diff --git a/src/app/OperationalDeviceProxy.h b/src/app/OperationalDeviceProxy.h
index a1623c1..3afc0a2 100644
--- a/src/app/OperationalDeviceProxy.h
+++ b/src/app/OperationalDeviceProxy.h
@@ -110,15 +110,6 @@
mAddressLookupHandle.SetListener(this);
}
- OperationalDeviceProxy(DeviceProxyInitParams & params, PeerId peerId, const Dnssd::ResolvedNodeData & nodeResolutionData) :
- OperationalDeviceProxy(params, peerId)
- {
- mAddressLookupHandle.SetListener(this);
- OnNodeIdResolved(nodeResolutionData);
- }
-
- void Clear();
-
/*
* This function can be called to establish a secure session with the device.
*
@@ -128,17 +119,28 @@
* On establishing the session, the callback function `onConnection` will be called. If the
* session setup fails, `onFailure` will be called.
*
- * If the session already exists, `onConnection` will be called immediately.
- * If the resolver is null and the device state is State::NeedsAddress, CHIP_ERROR_INVALID_ARGUMENT will be
- * returned.
+ * If the session already exists, `onConnection` will be called immediately,
+ * before the Connect call returns.
+ *
+ * `onFailure` may be called before the Connect call returns, for error
+ * cases that are detected synchronously (e.g. inability to start an address
+ * lookup).
*/
- CHIP_ERROR Connect(Callback::Callback<OnDeviceConnected> * onConnection,
- Callback::Callback<OnDeviceConnectionFailure> * onFailure);
+ void Connect(Callback::Callback<OnDeviceConnected> * onConnection, Callback::Callback<OnDeviceConnectionFailure> * onFailure);
bool IsConnected() const { return mState == State::SecureConnected; }
bool IsConnecting() const { return mState == State::Connecting; }
+ /**
+ * IsResolvingAddress returns true if we are doing an address resolution
+ * that needs to happen before we can establish CASE. We can be in the
+ * middle of doing address updates at other times too (e.g. when we are
+ * IsConnected()), but those will not cause a true return from
+ * IsResolvingAddress().
+ */
+ bool IsResolvingAddress() const { return mState == State::ResolvingAddress; }
+
//////////// SessionEstablishmentDelegate Implementation ///////////////
void OnSessionEstablished(const SessionHandle & session) override;
void OnSessionEstablishmentError(CHIP_ERROR error) override;
@@ -149,18 +151,6 @@
*/
void OnSessionReleased() override;
- void OnNodeIdResolved(const Dnssd::ResolvedNodeData & nodeResolutionData)
- {
- mDeviceAddress = ToPeerAddress(nodeResolutionData);
-
- mRemoteMRPConfig = nodeResolutionData.resolutionData.GetMRPConfig();
-
- if (mState == State::NeedsAddress)
- {
- mState = State::Initialized;
- }
- }
-
/**
* Mark any open session with the device as expired.
*/
@@ -168,14 +158,6 @@
NodeId GetDeviceId() const override { return mPeerId.GetNodeId(); }
- /**
- * Update data of the device.
- * This function will set new IP address, port and MRP retransmission intervals of the device.
- * Since the device settings might have been moved from RAM to the persistent storage, the function
- * will load the device settings first, before making the changes.
- */
- CHIP_ERROR UpdateDeviceData(const Transport::PeerAddress & addr, const ReliableMessageProtocolConfig & config);
-
PeerId GetPeerId() const { return mPeerId; }
CHIP_ERROR ShutdownSubscriptions() override;
@@ -227,11 +209,12 @@
private:
enum class State
{
- Uninitialized,
- NeedsAddress,
- Initialized,
- Connecting,
- SecureConnected,
+ Uninitialized, // Error state: OperationalDeviceProxy is useless
+ NeedsAddress, // No address known, lookup not started yet.
+ ResolvingAddress, // Address lookup in progress.
+ HasAddress, // Have an address, CASE handshake not started yet.
+ Connecting, // CASE handshake in progress.
+ SecureConnected, // CASE session established.
};
DeviceProxyInitParams mInitParams;
@@ -285,6 +268,11 @@
*
*/
void DequeueConnectionCallbacks(CHIP_ERROR error);
+
+ /**
+ * This function will set new IP address, port and MRP retransmission intervals of the device.
+ */
+ void UpdateDeviceData(const Transport::PeerAddress & addr, const ReliableMessageProtocolConfig & config);
};
} // namespace chip
diff --git a/src/app/OperationalDeviceProxyPool.h b/src/app/OperationalDeviceProxyPool.h
index e8092e1..c6f3d7e 100644
--- a/src/app/OperationalDeviceProxyPool.h
+++ b/src/app/OperationalDeviceProxyPool.h
@@ -28,9 +28,6 @@
public:
virtual OperationalDeviceProxy * Allocate(DeviceProxyInitParams & params, PeerId peerId) = 0;
- virtual OperationalDeviceProxy * Allocate(DeviceProxyInitParams & params, PeerId peerId,
- const Dnssd::ResolvedNodeData & nodeResolutionData) = 0;
-
virtual void Release(OperationalDeviceProxy * device) = 0;
virtual OperationalDeviceProxy * FindDevice(PeerId peerId) = 0;
@@ -53,12 +50,6 @@
return mDevicePool.CreateObject(params, peerId);
}
- OperationalDeviceProxy * Allocate(DeviceProxyInitParams & params, PeerId peerId,
- const Dnssd::ResolvedNodeData & nodeResolutionData) override
- {
- return mDevicePool.CreateObject(params, peerId, nodeResolutionData);
- }
-
void Release(OperationalDeviceProxy * device) override { mDevicePool.ReleaseObject(device); }
OperationalDeviceProxy * FindDevice(PeerId peerId) override
diff --git a/src/app/clusters/bindings/BindingManager.cpp b/src/app/clusters/bindings/BindingManager.cpp
index b95ff3c..ce52f52 100644
--- a/src/app/clusters/bindings/BindingManager.cpp
+++ b/src/app/clusters/bindings/BindingManager.cpp
@@ -117,9 +117,10 @@
VerifyOrReturnError(mInitParams.mCASESessionManager != nullptr, CHIP_ERROR_INCORRECT_STATE);
PeerId peer = PeerIdForNode(mInitParams.mFabricTable, fabric, node);
VerifyOrReturnError(peer.GetNodeId() != kUndefinedNodeId, CHIP_ERROR_NOT_FOUND);
- CHIP_ERROR error =
- mInitParams.mCASESessionManager->FindOrEstablishSession(peer, &mOnConnectedCallback, &mOnConnectionFailureCallback);
- if (error == CHIP_ERROR_NO_MEMORY)
+
+ mLastSessionEstablishmentError = CHIP_NO_ERROR;
+ mInitParams.mCASESessionManager->FindOrEstablishSession(peer, &mOnConnectedCallback, &mOnConnectionFailureCallback);
+ if (mLastSessionEstablishmentError == CHIP_ERROR_NO_MEMORY)
{
// Release the least recently used entry
// TODO: Some reference counting mechanism shall be added the CASESessionManager
@@ -132,11 +133,11 @@
PeerId lruPeer = PeerIdForNode(mInitParams.mFabricTable, fabricToRemove, nodeToRemove);
mInitParams.mCASESessionManager->ReleaseSession(lruPeer);
// Now retry
- error =
- mInitParams.mCASESessionManager->FindOrEstablishSession(peer, &mOnConnectedCallback, &mOnConnectionFailureCallback);
+ mLastSessionEstablishmentError = CHIP_NO_ERROR;
+ mInitParams.mCASESessionManager->FindOrEstablishSession(peer, &mOnConnectedCallback, &mOnConnectionFailureCallback);
}
}
- return error;
+ return mLastSessionEstablishmentError;
}
void BindingManager::HandleDeviceConnected(void * context, OperationalDeviceProxy * device)
@@ -178,6 +179,7 @@
// Simply release the entry, the connection will be re-established as needed.
ChipLogError(AppServer, "Failed to establish connection to node 0x" ChipLogFormatX64, ChipLogValueX64(peerId.GetNodeId()));
mInitParams.mCASESessionManager->ReleaseSession(peerId);
+ mLastSessionEstablishmentError = error;
}
void BindingManager::FabricRemoved(FabricIndex fabricIndex)
diff --git a/src/app/clusters/bindings/BindingManager.h b/src/app/clusters/bindings/BindingManager.h
index 91455a9..86b0179 100644
--- a/src/app/clusters/bindings/BindingManager.h
+++ b/src/app/clusters/bindings/BindingManager.h
@@ -137,6 +137,9 @@
Callback::Callback<OnDeviceConnected> mOnConnectedCallback;
Callback::Callback<OnDeviceConnectionFailure> mOnConnectionFailureCallback;
+
+ // Used to keep track of synchronous failures from FindOrEstablishSession.
+ CHIP_ERROR mLastSessionEstablishmentError;
};
} // namespace chip
diff --git a/src/app/clusters/ota-requestor/DefaultOTARequestor.cpp b/src/app/clusters/ota-requestor/DefaultOTARequestor.cpp
index cb10171..91d3182 100644
--- a/src/app/clusters/ota-requestor/DefaultOTARequestor.cpp
+++ b/src/app/clusters/ota-requestor/DefaultOTARequestor.cpp
@@ -376,15 +376,9 @@
ChipLogDetail(SoftwareUpdate, "Establishing session to provider node ID 0x" ChipLogFormatX64 " on fabric index %d",
ChipLogValueX64(mProviderLocation.Value().providerNodeID), mProviderLocation.Value().fabricIndex);
- CHIP_ERROR err =
- mCASESessionManager->FindOrEstablishSession(fabricInfo->GetPeerIdForNode(mProviderLocation.Value().providerNodeID),
- &mOnConnectedCallback, &mOnConnectionFailureCallback);
- if (err != CHIP_NO_ERROR)
- {
- ChipLogError(SoftwareUpdate, "Cannot establish connection to provider: %" CHIP_ERROR_FORMAT, err.Format());
- RecordErrorUpdateState(CHIP_ERROR_INCORRECT_STATE);
- return;
- }
+
+ mCASESessionManager->FindOrEstablishSession(fabricInfo->GetPeerIdForNode(mProviderLocation.Value().providerNodeID),
+ &mOnConnectedCallback, &mOnConnectionFailureCallback);
}
void DefaultOTARequestor::DisconnectFromProvider()
diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp
index 75c99b6..1b01c19 100644
--- a/src/controller/CHIPDeviceController.cpp
+++ b/src/controller/CHIPDeviceController.cpp
@@ -2179,16 +2179,11 @@
OperationalDeviceProxy * DeviceCommissioner::GetDeviceSession(const PeerId & peerId)
{
- CHIP_ERROR err = mSystemState->CASESessionMgr()->FindOrEstablishSession(peerId, &mOnDeviceConnectedCallback,
- &mOnDeviceConnectionFailureCallback);
+ mSystemState->CASESessionMgr()->FindOrEstablishSession(peerId, &mOnDeviceConnectedCallback,
+ &mOnDeviceConnectionFailureCallback);
- if (err != CHIP_NO_ERROR)
- {
- ChipLogError(Controller, "Failed to establish new session: %" CHIP_ERROR_FORMAT, err.Format());
- return nullptr;
- }
-
- // session should have been created now, expect this to return non-null
+ // If there is an OperationalDeviceProxy for this peerId now the call to the
+ // superclass will return it.
return DeviceController::GetDeviceSession(peerId);
}
diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h
index d246284..ce8b48e 100644
--- a/src/controller/CHIPDeviceController.h
+++ b/src/controller/CHIPDeviceController.h
@@ -168,16 +168,25 @@
CHIP_ERROR GetPeerAddressAndPort(PeerId peerId, Inet::IPAddress & addr, uint16_t & port);
/**
- * This function finds the device corresponding to deviceId, and establishes a secure connection with it.
- * Once the connection is successfully establishes (or if it's already connected), it calls `onConnectedDevice`
- * callback. If it fails to establish the connection, it calls `onError` callback.
+ * This function finds the device corresponding to deviceId, and establishes
+ * a CASE session with it.
+ *
+ * Once the CASE session is successfully established the `onConnectedDevice`
+ * callback is called. This can happen before GetConnectedDevice returns if
+ * there is an existing CASE session.
+ *
+ * If a CASE sessions fails to be established, the `onError` callback will
+ * be called. This can also happen before GetConnectedDevice returns.
+ *
+ * An error return from this function means that neither callback has been
+ * called yet, and neither callback will be called in the future.
*/
CHIP_ERROR GetConnectedDevice(NodeId deviceId, Callback::Callback<OnDeviceConnected> * onConnection,
chip::Callback::Callback<OnDeviceConnectionFailure> * onFailure)
{
VerifyOrReturnError(mState == State::Initialized && mFabricInfo != nullptr, CHIP_ERROR_INCORRECT_STATE);
- return mSystemState->CASESessionMgr()->FindOrEstablishSession(mFabricInfo->GetPeerIdForNode(deviceId), onConnection,
- onFailure);
+ mSystemState->CASESessionMgr()->FindOrEstablishSession(mFabricInfo->GetPeerIdForNode(deviceId), onConnection, onFailure);
+ return CHIP_NO_ERROR;
}
/**