@decentnetwork/peer 0.1.113 → 0.1.114
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/peer.js +56 -16
- package/package.json +1 -1
package/dist/peer.js
CHANGED
|
@@ -340,6 +340,14 @@ export class Peer {
|
|
|
340
340
|
* When a DHT packet later arrives from one of these sources, its sender pk
|
|
341
341
|
* is that friend's CURRENT DHT key — see #refreshFriendDhtKeyFromDht. */
|
|
342
342
|
#lanProbeTargets = new Map();
|
|
343
|
+
/** Exclusive turn-taking for OWN-HOST probe targets. Own-host targets
|
|
344
|
+
* (our IPs + loopback at native ports) are shared by every stranded
|
|
345
|
+
* friend, so concurrent probes overwrite each other's #lanProbeTargets
|
|
346
|
+
* mapping and the reply gets credited to whoever probed last (observed
|
|
347
|
+
* live: the simulator's key landed on an unrelated friend). One friend
|
|
348
|
+
* holds the slot at a time; per-friend candidate probes are unaffected. */
|
|
349
|
+
#ownHostProbeFriendId;
|
|
350
|
+
#ownHostProbeUntilMs = 0;
|
|
343
351
|
#dhtMaintenanceTimer;
|
|
344
352
|
// Per-friend last DHT-PK send time, keyed by friendId, used even when no
|
|
345
353
|
// session entry exists yet so the connection loop does not flood DHT-PK
|
|
@@ -5188,6 +5196,7 @@ export class Peer {
|
|
|
5188
5196
|
};
|
|
5189
5197
|
const tried = new Set();
|
|
5190
5198
|
// (b) known candidates — refresh a rotated DHT key at a live endpoint.
|
|
5199
|
+
// Per-friend targets: no mapping ambiguity, always allowed.
|
|
5191
5200
|
for (const candidate of connectCandidates) {
|
|
5192
5201
|
const key = `${candidate.host}:${candidate.port}`;
|
|
5193
5202
|
if (tried.has(key))
|
|
@@ -5196,17 +5205,25 @@ export class Peer {
|
|
|
5196
5205
|
await probe(candidate.host, candidate.port, false); // cookie already sent above
|
|
5197
5206
|
}
|
|
5198
5207
|
// (a)+(b) own-host targets — find a same-host peer after an IP change.
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5208
|
+
// SHARED targets: only the current slot holder probes them, so the
|
|
5209
|
+
// reply maps to exactly one friend. Slot rotates by expiry; the
|
|
5210
|
+
// cookie backoff staggers contenders so every stranded friend
|
|
5211
|
+
// eventually gets a turn.
|
|
5212
|
+
if (this.#ownHostProbeFriendId === friendId || probeNow >= this.#ownHostProbeUntilMs) {
|
|
5213
|
+
this.#ownHostProbeFriendId = friendId;
|
|
5214
|
+
this.#ownHostProbeUntilMs = probeNow + 10_000;
|
|
5215
|
+
for (const host of [...getLocalIpv4Addresses(), "127.0.0.1"]) {
|
|
5216
|
+
if (isOwnVirtualAddress(host))
|
|
5217
|
+
continue; // never probe into the overlay
|
|
5218
|
+
for (const port of LAN_SWEEP_PORTS) {
|
|
5219
|
+
if (port === ourLocalPort)
|
|
5220
|
+
continue; // our own socket
|
|
5221
|
+
const key = `${host}:${port}`;
|
|
5222
|
+
if (tried.has(key))
|
|
5223
|
+
continue;
|
|
5224
|
+
tried.add(key);
|
|
5225
|
+
await probe(host, port, true);
|
|
5226
|
+
}
|
|
5210
5227
|
}
|
|
5211
5228
|
}
|
|
5212
5229
|
}
|
|
@@ -5237,9 +5254,18 @@ export class Peer {
|
|
|
5237
5254
|
}
|
|
5238
5255
|
catch (error) {
|
|
5239
5256
|
this.#debugLog(`cookie request send failed for ${friendId}: ${error.message}`);
|
|
5257
|
+
// A failed send is still a failed ATTEMPT: count it so (a) backoff
|
|
5258
|
+
// grows instead of hammering a dead address at base cadence forever,
|
|
5259
|
+
// and (b) the rescue probes (gated on retryCount >= 1) still fire for
|
|
5260
|
+
// a friend whose sole candidate errors at the syscall level — before
|
|
5261
|
+
// this, such a friend never probed and could never be rescued.
|
|
5262
|
+
this.#cookieRetryCount.set(friendId, (this.#cookieRetryCount.get(friendId) ?? 0) + 1);
|
|
5240
5263
|
session.pendingEcho = undefined;
|
|
5241
5264
|
session.pendingCookiePeerDhtPublicKey = undefined;
|
|
5242
|
-
|
|
5265
|
+
// Keep cookieRequestSentMs (set at attempt start): it is the loop's
|
|
5266
|
+
// `lastAttempt`. Clearing it made lastAttempt 0, so the cooldown gate
|
|
5267
|
+
// always passed and a friend whose sends error retried every 250ms
|
|
5268
|
+
// tick forever — the "cookie request send failed" log flood.
|
|
5243
5269
|
return false;
|
|
5244
5270
|
}
|
|
5245
5271
|
}
|
|
@@ -5486,11 +5512,25 @@ export class Peer {
|
|
|
5486
5512
|
}
|
|
5487
5513
|
if (!friendId)
|
|
5488
5514
|
return;
|
|
5489
|
-
// The sender
|
|
5490
|
-
//
|
|
5515
|
+
// The sender pk currently maps to a DIFFERENT friend. If that friend's
|
|
5516
|
+
// session is ESTABLISHED, the key genuinely belongs to them — don't
|
|
5517
|
+
// cross-wire. If it is NOT established, the mapping itself may be a
|
|
5518
|
+
// mis-credited earlier probe reply (shared own-host targets), and
|
|
5519
|
+
// refusing here would permanently lock the true owner out — steal it
|
|
5520
|
+
// and scrub the other friend's stale copy so routing stops confusing
|
|
5521
|
+
// the two. A wrong steal self-corrects: the real-key handshake cannot
|
|
5522
|
+
// complete against the wrong node.
|
|
5491
5523
|
const byDht = this.#friendByDhtPk(senderId);
|
|
5492
|
-
if (byDht && byDht.friendId !== friendId)
|
|
5493
|
-
|
|
5524
|
+
if (byDht && byDht.friendId !== friendId) {
|
|
5525
|
+
const otherSession = this.#friendSessions.get(byDht.friendId);
|
|
5526
|
+
if (otherSession?.established)
|
|
5527
|
+
return;
|
|
5528
|
+
this.#debugLog(`dht_key_steal ${senderId} from=${byDht.friendId} to=${friendId} (other unestablished)`);
|
|
5529
|
+
if (otherSession?.friendDhtPublicKey && Buffer.from(otherSession.friendDhtPublicKey).equals(Buffer.from(senderDhtPk))) {
|
|
5530
|
+
otherSession.friendDhtPublicKey = undefined;
|
|
5531
|
+
}
|
|
5532
|
+
this.#friendDhtKeys.delete(byDht.friendId);
|
|
5533
|
+
}
|
|
5494
5534
|
if (senderId === friendId)
|
|
5495
5535
|
return; // already keyed by real pk — nothing to refresh
|
|
5496
5536
|
const session = this.#friendSessions.get(friendId);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/peer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.114",
|
|
4
4
|
"description": "Pure TypeScript port of Elastos Carrier (toxcore-derived) P2P messaging. DHT, onion routing, TCP relay, FlatBuffers app payloads, Express offline relay. Wire-compatible with iOS Beagle and the Carrier C SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|