Skip to content

Commit

Permalink
Handle M_MAX_DELAY_EXCEEDED errors (#4511)
Browse files Browse the repository at this point in the history
* Handle M_MAX_DELAY_EXCEEDED errors

Use a lower delay time if the server rejects a delay as too long.

* Add test

* Lint test

* Update src/matrixrtc/MatrixRTCSession.ts

Co-authored-by: Robin <robin@robin.town>

* Test computed expiry timeout value

---------

Co-authored-by: Robin <robin@robin.town>
  • Loading branch information
AndrewFerr and robintown authored Nov 11, 2024
1 parent 581b320 commit 35d862e
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
22 changes: 21 additions & 1 deletion spec/unit/matrixrtc/MatrixRTCSession.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,19 @@ describe("MatrixRTCSession", () => {

jest.useFakeTimers();

// preparing the delayed disconnect should handle the delay being too long
const sendDelayedStateExceedAttempt = new Promise<void>((resolve) => {
const error = new MatrixError({
"errcode": "M_UNKNOWN",
"org.matrix.msc4140.errcode": "M_MAX_DELAY_EXCEEDED",
"org.matrix.msc4140.max_delay": 7500,
});
sendDelayedStateMock.mockImplementationOnce(() => {
resolve();
return Promise.reject(error);
});
});

// preparing the delayed disconnect should handle ratelimiting
const sendDelayedStateAttempt = new Promise<void>((resolve) => {
const error = new MatrixError({ errcode: "M_LIMIT_EXCEEDED" });
Expand Down Expand Up @@ -541,7 +554,14 @@ describe("MatrixRTCSession", () => {
});
});

sess!.joinRoomSession([activeFocusConfig], activeFocus, { useLegacyMemberEvents: false });
sess!.joinRoomSession([activeFocusConfig], activeFocus, {
useLegacyMemberEvents: false,
membershipServerSideExpiryTimeout: 9000,
});

expect(sess).toHaveProperty("membershipServerSideExpiryTimeout", 9000);
await sendDelayedStateExceedAttempt.then(); // needed to resolve after the send attempt catches
expect(sess).toHaveProperty("membershipServerSideExpiryTimeout", 7500);

await sendDelayedStateAttempt;
jest.advanceTimersByTime(5000);
Expand Down
26 changes: 25 additions & 1 deletion src/matrixrtc/MatrixRTCSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,18 @@ export class MatrixRTCSession extends TypedEventEmitter<MatrixRTCSessionEvent, M
return this.joinConfig?.useKeyDelay ?? 5_000;
}

/**
* If the server disallows the configured {@link membershipServerSideExpiryTimeout},
* this stores a delay that the server does allow.
*/
private membershipServerSideExpiryTimeoutOverride?: number;

private get membershipServerSideExpiryTimeout(): number {
return this.joinConfig?.membershipServerSideExpiryTimeout ?? 8_000;
return (
this.membershipServerSideExpiryTimeoutOverride ??
this.joinConfig?.membershipServerSideExpiryTimeout ??
8_000
);
}

private get membershipKeepAlivePeriod(): number {
Expand Down Expand Up @@ -1141,6 +1151,20 @@ export class MatrixRTCSession extends TypedEventEmitter<MatrixRTCSessionEvent, M
);
this.disconnectDelayId = res.delay_id;
} catch (e) {
if (
e instanceof MatrixError &&
e.errcode === "M_UNKNOWN" &&
e.data["org.matrix.msc4140.errcode"] === "M_MAX_DELAY_EXCEEDED"
) {
const maxDelayAllowed = e.data["org.matrix.msc4140.max_delay"];
if (
typeof maxDelayAllowed === "number" &&
this.membershipServerSideExpiryTimeout > maxDelayAllowed
) {
this.membershipServerSideExpiryTimeoutOverride = maxDelayAllowed;
return prepareDelayedDisconnection();
}
}
logger.error("Failed to prepare delayed disconnection event:", e);
}
};
Expand Down

0 comments on commit 35d862e

Please # to comment.