Skip to content

Commit

Permalink
Allocate callbacks in EstablishConnection
Browse files Browse the repository at this point in the history
This allows multiple connection async establishments to multiple
nodes.
  • Loading branch information
tehampson committed Aug 25, 2022
1 parent bc56a4a commit 780e73b
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 31 deletions.
2 changes: 1 addition & 1 deletion examples/all-clusters-app/ameba/main/BindingHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation

void LightSwitchContextReleaseHandler(void * context)
{
VerifyOrReturn(context != nullptr, LOG_ERR("Invalid context for Light switch context release handler"););
VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "Invalid context for Light switch context release handler"));

Platform::Delete(static_cast<BindingCommandData *>(context));
}
Expand Down
2 changes: 1 addition & 1 deletion examples/light-switch-app/ameba/main/BindingHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation

void LightSwitchContextReleaseHandler(void * context)
{
VerifyOrReturn(context != nullptr, LOG_ERR("Invalid context for Light switch context release handler"););
VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "Invalid context for Light switch context release handler"));

Platform::Delete(static_cast<BindingCommandData *>(context));
}
Expand Down
2 changes: 1 addition & 1 deletion examples/light-switch-app/esp32/main/BindingHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation

void LightSwitchContextReleaseHandler(void * context)
{
VerifyOrReturn(context != nullptr, LOG_ERR("Invalid context for Light switch context release handler"););
VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "Invalid context for Light switch context release handler"));

Platform::Delete(static_cast<BindingCommandData *>(context));
}
Expand Down
2 changes: 1 addition & 1 deletion examples/light-switch-app/telink/src/binding-handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, Operation

void LightSwitchContextReleaseHandler(void * context)
{
VerifyOrReturn(context != nullptr, LOG_ERR("Invalid context for Light switch context release handler"););
VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "Invalid context for Light switch context release handler"));

Platform::Delete(static_cast<BindingCommandData *>(context));
}
Expand Down
28 changes: 12 additions & 16 deletions src/app/clusters/bindings/BindingManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,31 +101,28 @@ CHIP_ERROR BindingManager::EstablishConnection(const ScopedNodeId & nodeId)
VerifyOrReturnError(mInitParams.mCASESessionManager != nullptr, CHIP_ERROR_INCORRECT_STATE);

mLastSessionEstablishmentError = CHIP_NO_ERROR;
mInitParams.mCASESessionManager->FindOrEstablishSession(nodeId, &mOnConnectedCallback, &mOnConnectionFailureCallback);
auto * connectionCallback = Platform::New<ConnectionCallback>(this);
mInitParams.mCASESessionManager->FindOrEstablishSession(nodeId, connectionCallback->GetOnDeviceConnected(),
connectionCallback->GetOnDeviceConnectionFailure());
if (mLastSessionEstablishmentError == CHIP_ERROR_NO_MEMORY)
{
// Release the least recently used entry
// TODO: Some reference counting mechanism shall be added the CASESessionManager
// so that other session clients don't get accidentally closed.
ScopedNodeId peerToRemove;
if (mPendingNotificationMap.FindLRUConnectPeer(peerToRemove) == CHIP_NO_ERROR)
{
mPendingNotificationMap.RemoveAllEntriesForNode(peerToRemove);

// Now retry
mLastSessionEstablishmentError = CHIP_NO_ERROR;
mInitParams.mCASESessionManager->FindOrEstablishSession(nodeId, &mOnConnectedCallback, &mOnConnectionFailureCallback);
// At this point connectionCallback is null since it deletes itself when the callback is called.
connectionCallback = Platform::New<ConnectionCallback>(this);
mInitParams.mCASESessionManager->FindOrEstablishSession(nodeId, connectionCallback->GetOnDeviceConnected(),
connectionCallback->GetOnDeviceConnectionFailure());
}
}
return mLastSessionEstablishmentError;
}

void BindingManager::HandleDeviceConnected(void * context, Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle)
{
BindingManager * manager = static_cast<BindingManager *>(context);
manager->HandleDeviceConnected(exchangeMgr, sessionHandle);
}

void BindingManager::HandleDeviceConnected(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle)
{
FabricIndex fabricToRemove = kUndefinedFabricIndex;
Expand All @@ -149,17 +146,16 @@ void BindingManager::HandleDeviceConnected(Messaging::ExchangeManager & exchange
mPendingNotificationMap.RemoveAllEntriesForNode(ScopedNodeId(nodeToRemove, fabricToRemove));
}

void BindingManager::HandleDeviceConnectionFailure(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
{
BindingManager * manager = static_cast<BindingManager *>(context);
manager->HandleDeviceConnectionFailure(peerId, error);
}

void BindingManager::HandleDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error)
{
// 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()));
mLastSessionEstablishmentError = error;
// We don't release the entry when connection fails, because inside
// BindingManager::EstablishConnection we may try again the connection. The logic in there
// doesn't actually make any sense with how mPendingNotificationMap and
// CASESessionManager are implemented today, but the risk of making changes close to 1.0 release
// prevents us from cleaning this up at the moment.
}

void BindingManager::FabricRemoved(FabricIndex fabricIndex)
Expand Down
44 changes: 33 additions & 11 deletions src/app/clusters/bindings/BindingManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,7 @@ struct BindingManagerInitParams
class BindingManager
{
public:
BindingManager() :
mOnConnectedCallback(HandleDeviceConnected, this), mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this)
{}
BindingManager() {}

void RegisterBoundDeviceChangedHandler(BoundDeviceChangedHandler handler) { mBoundDeviceChangedHandler = handler; }

Expand Down Expand Up @@ -123,22 +121,46 @@ class BindingManager
static BindingManager & GetInstance() { return sBindingManager; }

private:
static BindingManager sBindingManager;

static void HandleDeviceConnected(void * context, Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle);
void HandleDeviceConnected(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle);
class ConnectionCallback
{
public:
ConnectionCallback(BindingManager * bindingManager) :
mBindingManager(bindingManager), mOnConnectedCallback(HandleDeviceConnected, this),
mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this)
{}

Callback::Callback<OnDeviceConnected> * GetOnDeviceConnected() { return &mOnConnectedCallback; }
Callback::Callback<OnDeviceConnectionFailure> * GetOnDeviceConnectionFailure() { return &mOnConnectionFailureCallback; }

private:
static void HandleDeviceConnected(void * context, Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle)
{
ConnectionCallback * connectionCallback = static_cast<ConnectionCallback *>(context);
connectionCallback->mBindingManager->HandleDeviceConnected(exchangeMgr, sessionHandle);
Platform::Delete(connectionCallback);
}
static void HandleDeviceConnectionFailure(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
{
ConnectionCallback * connectionCallback = static_cast<ConnectionCallback *>(context);
connectionCallback->mBindingManager->HandleDeviceConnectionFailure(peerId, error);
Platform::Delete(connectionCallback);
}

BindingManager * mBindingManager;
Callback::Callback<OnDeviceConnected> mOnConnectedCallback;
Callback::Callback<OnDeviceConnectionFailure> mOnConnectionFailureCallback;
};

static void HandleDeviceConnectionFailure(void * context, const ScopedNodeId & peerId, CHIP_ERROR error);
void HandleDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error);
static BindingManager sBindingManager;

CHIP_ERROR EstablishConnection(const ScopedNodeId & nodeId);

PendingNotificationMap mPendingNotificationMap;
BoundDeviceChangedHandler mBoundDeviceChangedHandler;
BindingManagerInitParams mInitParams;

Callback::Callback<OnDeviceConnected> mOnConnectedCallback;
Callback::Callback<OnDeviceConnectionFailure> mOnConnectionFailureCallback;
void HandleDeviceConnected(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle);
void HandleDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error);

// Used to keep track of synchronous failures from FindOrEstablishSession.
CHIP_ERROR mLastSessionEstablishmentError;
Expand Down

0 comments on commit 780e73b

Please sign in to comment.