Skip to content

Commit

Permalink
Merge pull request #1959 from ably/ECO-5043/dont-abort-on-unknown-action
Browse files Browse the repository at this point in the history
[ECO-5043] Don't abort connection on unknown message action
  • Loading branch information
VeskeR authored Jan 28, 2025
2 parents 4d06795 + 923e42b commit b168d96
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
7 changes: 3 additions & 4 deletions src/common/lib/client/realtimechannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { EncodingDecodingContext, CipherOptions, populateFieldsFromParent } from
import Message, { WireMessage, getMessagesSize, encodeArray as encodeMessagesArray } from '../types/message';
import ChannelStateChange from './channelstatechange';
import ErrorInfo, { PartialErrorInfo } from '../types/errorinfo';
import ConnectionErrors from '../transport/connectionerrors';
import * as API from '../../../../ably';
import ConnectionManager from '../transport/connectionmanager';
import ConnectionStateChange from './connectionstatechange';
Expand Down Expand Up @@ -662,13 +661,13 @@ class RealtimeChannel extends EventEmitter {
}

default:
// RSF1, should handle unrecognized message actions gracefully and don't abort the realtime connection to ensure forward compatibility
Logger.logAction(
this.logger,
Logger.LOG_ERROR,
Logger.LOG_MAJOR,
'RealtimeChannel.processMessage()',
'Fatal protocol error: unrecognised action (' + message.action + ')',
'Protocol error: unrecognised message action (' + message.action + ')',
);
this.connectionManager.abort(ConnectionErrors.unknownChannelErr());
}
}

Expand Down
40 changes: 40 additions & 0 deletions test/realtime/message.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1487,5 +1487,45 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async
helper.closeAndFinish(done, realtime, err);
}
});

/** @spec RSF1 */
it('unrecognized message action', async function () {
const helper = this.test.helper;
const realtime = helper.AblyRealtime();

let caughtError;
try {
await helper.monitorConnectionAsync(async () => {
const channel = realtime.channels.get('unknown_action');
await channel.attach();

helper.recordPrivateApi('call.connectionManager.activeProtocol.getTransport');
helper.recordPrivateApi('call.transport.onProtocolMessage');
realtime.connection.connectionManager.activeProtocol
.getTransport()
.onProtocolMessage({ action: Number.MAX_SAFE_INTEGER, channel: channel.name });

// wait for the next event loop so connection can process any pending callbacks and go to a failed state
await new Promise((res, rej) =>
setTimeout(() => {
try {
expect(realtime.connection.state).to.equal(
'connected',
'Check still connected after unrecognized action field',
);
res();
} catch (error) {
rej(error);
}
}, 0),
);
}, realtime);
} catch (error) {
caughtError = error;
}

expect(caughtError, 'Check connection was not closed after receiving unrecognized message action').to.not.exist;
await helper.closeAndFinishAsync(realtime);
});
});
});

0 comments on commit b168d96

Please sign in to comment.