@actuallab/rpc 14.3.16 → 14.3.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1285,6 +1285,15 @@ var RpcSystemCallHandler = class {
1285
1285
  );
1286
1286
  return;
1287
1287
  }
1288
+ if (!peer.tryClaimReconnect()) {
1289
+ peer.hub.systemCallSender.error(
1290
+ peer.connection,
1291
+ peer.serializationFormat,
1292
+ relatedId,
1293
+ new Error("TooLateToReconnect: this connection was already reconnected")
1294
+ );
1295
+ return;
1296
+ }
1288
1297
  let unknownIds = [];
1289
1298
  try {
1290
1299
  const stagesRaw = args[1];
@@ -2749,6 +2758,9 @@ var RpcPeer = class {
2749
2758
  * stale `$sys.Reconnect` that references an older connection generation
2750
2759
  * (C# `RpcSystemCalls.Reconnect`'s `ownHandshake.Index` check). */
2751
2760
  _ownHandshakeIndex = 0;
2761
+ /** Whether the current connection generation has already used its single
2762
+ * `$sys.Reconnect`. Mirrors C# `RpcPeerConnectionState.TryClaimReconnect`. */
2763
+ _isReconnectClaimed = false;
2752
2764
  _connection;
2753
2765
  /** Mirror of `_connectionState === Connected`. True only after the
2754
2766
  * handshake round-trip completes; outbound `call()` checks this to
@@ -2819,6 +2831,19 @@ var RpcPeer = class {
2819
2831
  get ownHandshakeIndex() {
2820
2832
  return this._ownHandshakeIndex;
2821
2833
  }
2834
+ // A conforming peer sends `$sys.Reconnect` at most once per connection, so anything
2835
+ // beyond that is a replay - and the reconciliation it performs is proportional to the
2836
+ // call ids it carries, with nothing else capping how often it can arrive.
2837
+ tryClaimReconnect() {
2838
+ if (this._isReconnectClaimed)
2839
+ return false;
2840
+ this._isReconnectClaimed = true;
2841
+ return true;
2842
+ }
2843
+ nextOwnHandshakeIndex() {
2844
+ this._isReconnectClaimed = false;
2845
+ return ++this._ownHandshakeIndex;
2846
+ }
2822
2847
  _setConnectionState(value) {
2823
2848
  if (this._connectionState === value) return;
2824
2849
  const previousState = this._connectionState;
@@ -3354,7 +3379,7 @@ var RpcClientPeer = class extends RpcPeer {
3354
3379
  this.serializationFormat,
3355
3380
  this.id,
3356
3381
  this.hub.hubId,
3357
- ++this._ownHandshakeIndex
3382
+ this.nextOwnHandshakeIndex()
3358
3383
  );
3359
3384
  } catch (e) {
3360
3385
  warnLog7?.log(`'${this.ref}': Failed to send handshake`, e);
@@ -3619,7 +3644,7 @@ var RpcServerPeer = class extends RpcPeer {
3619
3644
  this.serializationFormat,
3620
3645
  this.id,
3621
3646
  this.hub.hubId,
3622
- ++this._ownHandshakeIndex
3647
+ this.nextOwnHandshakeIndex()
3623
3648
  );
3624
3649
  this._setConnectionState(3 /* Connected */);
3625
3650
  }