Skip to content

Commit

Permalink
No Resubscribe after disconnect (#1574)
Browse files Browse the repository at this point in the history
* No Resubscribe after disconnect

Mke sure that also subscriptions and these things get removed when a node gets removed and not just deleted

* Ignore channel errors on session destroy

* Adjust disconnect

* rely on underlaying logic to cancel subscriptions

* revert unneeded change. we fixed in PeerSet
  • Loading branch information
Apollon77 authored Dec 28, 2024
1 parent 16c32ba commit cf96b78
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 22 deletions.
11 changes: 6 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,18 @@ The main work (all changes without a GitHub username in brackets in the below li
- Feature: Allows to update the Fabric Label during controller runtime using `updateFabricLabel()` on CommissioningController
- Enhancement: Improves Reconnection Handling for devices that use persisted subscriptions
- Enhancement: Use data type definitions from Model for Controller Device type definitions
- Fix: When a paired node gets disconnected (or decommissioned) invalidate subscription handlers to prevent reconnection tries

## 0.11.9 (2024-12-11)

- @matter/node
- BREAKING: WindowCovering: supportsCalibration is moved from state property to an internal property
- Enhancement: Enhances the number assertations to only allow finite numbers
- Enhancement: WindowCovering: Adds an internal property to disable the operational state and value management by the default implementation to allow device to handle this themselves
- BREAKING: WindowCovering: supportsCalibration is moved from state property to an internal property
- Fix: ColorControl: Do not try to convert color mode details if they are not defined
- Fix: ColorControl: colorMode attribute needs to be defined if HS feature is not used because the default value 0 is else invalid
- Enhancement: EventsBehavior allows for configuration of event buffering
- Enhancement: Matter protocol initialization now runs independently of and after behavior initialization, giving behaviors more flexibility in participating in protocol setup
- Fix: ColorControl: Do not try to convert color mode details if they are not defined
- Fix: ColorControl: colorMode attribute needs to be defined if HS feature is not used because the default value 0 is else invalid

- @matter/protocol
- Fix: Also retry next discovered address when a Channel establishment error for PASE occurs
Expand All @@ -58,18 +59,18 @@ The main work (all changes without a GitHub username in brackets in the below li
- Enhancement: Removes default value from attribute ColorMode of ColorControl cluster because feature specific enum value was used

- @project-chip/matter.js
- BREAKING: In `ContentLauncher` cluster `ParameterEnum` is renamed to `Parameter` and `Parameter` is renamed to `ParameterStruct`
- Feature: Introduces PairedNode#triggerReconnect() method to trigger a reconnection
- Enhancement: Considers a node in reconnection state that should be decommissioned as already factory reset
- Enhancement: Optimizes reconnection handling in Controller API
- Fix: Do not try to convert color mode details if they are not defined
- Fix: Clusters generated for extensions of base clusters such as Alarm Base and Mode Base now include full details of extended types; in particular extended enums such as Mode Tag were previously insufficiently defined
- BREAKING: In `ContentLauncher` cluster `ParameterEnum` is renamed to `Parameter` and `Parameter` is renamed to `ParameterStruct`

- @matter/model
- BREAKING: `ClusterModel` and `ValueModel` properties `members`, `activeMembers` and `conformantMembers` are removed; use `Scope#membersOf` instead
- Feature: New `Scope` component analyzes scope of a model, caches analysis results, and implements algorithms that require analysis to perform efficiently
- Enhancement: Models that define datatypes now inherit from common `ScopeModel` base class
- Fix: Extended enums and other types now report the full set of members via `Scope#membersOf`
- BREAKING: `ClusterModel` and `ValueModel` properties `members`, `activeMembers` and `conformantMembers` are removed; use `Scope#membersOf` instead

- @matter/protocol
- Feature: The algorithm that chooses event occurrences to discard when the buffer overflows is now smarter and configurable
Expand Down
18 changes: 11 additions & 7 deletions packages/matter.js/src/device/PairedNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,16 @@ export class PairedNode {
return this.#remoteInitializationDone || this.#localInitializationDone;
}

#invalidateSubscriptionHandler() {
if (this.#currentSubscriptionHandler !== undefined) {
// Make sure the former handlers do not trigger anymore
this.#currentSubscriptionHandler.attributeListener = () => {};
this.#currentSubscriptionHandler.eventListener = () => {};
this.#currentSubscriptionHandler.updateTimeoutHandler = () => {};
this.#currentSubscriptionHandler.subscriptionAlive = () => {};
}
}

#setConnectionState(state: NodeStates) {
if (
this.#connectionState === state ||
Expand Down Expand Up @@ -684,13 +694,7 @@ export class PairedNode {
this.#nodeDetails.determineSubscriptionParameters(this.options);
const { threadConnected } = this.#nodeDetails.meta ?? {};

if (this.#currentSubscriptionHandler !== undefined) {
// Make sure the former handlers do not trigger anymore
this.#currentSubscriptionHandler.attributeListener = () => {};
this.#currentSubscriptionHandler.eventListener = () => {};
this.#currentSubscriptionHandler.updateTimeoutHandler = () => {};
this.#currentSubscriptionHandler.subscriptionAlive = () => {};
}
this.#invalidateSubscriptionHandler();

const subscriptionHandler: SubscriptionHandlerCallbacks = {
attributeListener: (data, changed, oldValue) => {
Expand Down
11 changes: 3 additions & 8 deletions packages/protocol/src/peer/PeerSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,14 +327,9 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
/**
* Terminate any active peer connection.
*/
async disconnect(peer: PeerAddress | OperationalPeer) {
const address = this.get(peer)?.address;
if (address === undefined) {
return;
}

async disconnect(address: PeerAddress, sendSessionClose = true) {
this.#clients.get(address)?.removeAllSubscriptions();
await this.#sessions.removeAllSessionsForNode(address, true);
await this.#sessions.removeAllSessionsForNode(address, sendSessionClose);
await this.#channels.removeAllNodeChannels(address);
}

Expand All @@ -351,7 +346,7 @@ export class PeerSet implements ImmutableSet<OperationalPeer>, ObservableSet<Ope
logger.info(`Removing ${address}`);
this.#peers.delete(actual);
await this.#store.deletePeer(address);
await this.disconnect(actual);
await this.disconnect(address, false);
await this.#sessions.deleteResumptionRecord(address);
this.#clients.delete(address);
}
Expand Down
9 changes: 7 additions & 2 deletions packages/protocol/src/session/SecureSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { PeerAddress } from "#peer/PeerAddress.js";
import { CaseAuthenticatedTag, FabricIndex, NodeId, StatusCode, StatusResponseError } from "#types";
import { DecodedMessage, DecodedPacket, Message, MessageCodec, Packet } from "../codec/MessageCodec.js";
import { Fabric } from "../fabric/Fabric.js";
import { NoChannelError } from "../protocol/ChannelManager.js";
import { MessageCounter } from "../protocol/MessageCounter.js";
import { MessageReceptionStateEncryptedWithoutRollover } from "../protocol/MessageReceptionState.js";
import { Session, SessionParameterOptions } from "./Session.js";
Expand Down Expand Up @@ -313,9 +314,13 @@ export class SecureSession extends Session {
logger.info(`End ${this.isPase ? "PASE" : "CASE"} session ${this.name}`);
this.manager?.sessions.delete(this);

// Wait for the exchange to finish closing
// Wait for the exchange to finish closing, but ignore errors if channel is already closed
if (this.closer) {
await this.closer;
try {
await this.closer;
} catch (error) {
NoChannelError.accept(error);
}
}
}
}
Expand Down

0 comments on commit cf96b78

Please sign in to comment.