@decentnetwork/peer 0.1.68 → 0.1.69
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 +28 -34
- package/package.json +1 -1
package/dist/peer.js
CHANGED
|
@@ -1318,7 +1318,7 @@ export class Peer {
|
|
|
1318
1318
|
// poison the UDP send-back path.
|
|
1319
1319
|
const fromTcp = this.#remoteIsTcp(remote);
|
|
1320
1320
|
if (!fromTcp) {
|
|
1321
|
-
matchedSession
|
|
1321
|
+
this.#adoptRemote(matchedSession, remote.address, remote.port);
|
|
1322
1322
|
}
|
|
1323
1323
|
else {
|
|
1324
1324
|
matchedSession.hasTcpRoute = true;
|
|
@@ -1392,13 +1392,7 @@ export class Peer {
|
|
|
1392
1392
|
state.hasTcpRoute = true;
|
|
1393
1393
|
}
|
|
1394
1394
|
else {
|
|
1395
|
-
|
|
1396
|
-
// retransmitted via the public/hairpin endpoint must not knock us off
|
|
1397
|
-
// a locked physical-LAN path. Cheap string compare — no syscall.
|
|
1398
|
-
const lockedOnLan = !!state.lanRemoteHost && state.remote?.host === state.lanRemoteHost;
|
|
1399
|
-
if (!lockedOnLan || remote.address === state.lanRemoteHost) {
|
|
1400
|
-
state.remote = { host: remote.address, port: remote.port };
|
|
1401
|
-
}
|
|
1395
|
+
this.#adoptRemote(state, remote.address, remote.port);
|
|
1402
1396
|
}
|
|
1403
1397
|
state.lastPingRecvMs = Date.now();
|
|
1404
1398
|
this.#debugVerboseLog(`hs_recv duplicate friend=${friendId} remote=${remote.address}:${remote.port} (session preserved)`);
|
|
@@ -1488,13 +1482,7 @@ export class Peer {
|
|
|
1488
1482
|
// Don't set state.remote — there's no UDP endpoint for this peer.
|
|
1489
1483
|
}
|
|
1490
1484
|
else {
|
|
1491
|
-
|
|
1492
|
-
// re-handshake arriving over the public/hairpin endpoint downgrade us
|
|
1493
|
-
// off a locked physical-LAN path. Cheap string compare — no syscall.
|
|
1494
|
-
const lockedOnLan = !!state.lanRemoteHost && state.remote?.host === state.lanRemoteHost;
|
|
1495
|
-
if (!lockedOnLan || remote.address === state.lanRemoteHost) {
|
|
1496
|
-
state.remote = { host: remote.address, port: remote.port };
|
|
1497
|
-
}
|
|
1485
|
+
this.#adoptRemote(state, remote.address, remote.port);
|
|
1498
1486
|
}
|
|
1499
1487
|
if (isNewSession) {
|
|
1500
1488
|
state.sendPacketNumber = 0;
|
|
@@ -1664,22 +1652,12 @@ export class Peer {
|
|
|
1664
1652
|
state.lastRelayRecvMs = Date.now();
|
|
1665
1653
|
}
|
|
1666
1654
|
else {
|
|
1667
|
-
// Adopt the source as our send endpoint —
|
|
1668
|
-
//
|
|
1669
|
-
//
|
|
1670
|
-
// the
|
|
1671
|
-
//
|
|
1672
|
-
|
|
1673
|
-
// is made ONLY in the periodic offer/maintenance paths, which record the
|
|
1674
|
-
// locked peer LAN host in state.lanRemoteHost. Here in the per-packet hot
|
|
1675
|
-
// path we do a single string compare — NO interface syscall — so a
|
|
1676
|
-
// high-rate stream (CCTV: thousands of packets/sec) never pays for it.
|
|
1677
|
-
// (The per-packet getPhysicalLanSubnets() call this replaces was the
|
|
1678
|
-
// CCTV CPU regression.)
|
|
1679
|
-
const lockedOnLan = !!state.lanRemoteHost && state.remote?.host === state.lanRemoteHost;
|
|
1680
|
-
if (!lockedOnLan || remote.address === state.lanRemoteHost) {
|
|
1681
|
-
state.remote = { host: remote.address, port: remote.port };
|
|
1682
|
-
}
|
|
1655
|
+
// Adopt the source as our send endpoint — via #adoptRemote, which
|
|
1656
|
+
// refuses to downgrade off a locked physical-LAN path to a public /
|
|
1657
|
+
// Tailscale-exit hairpin source. Cheap string compare, NO interface
|
|
1658
|
+
// syscall (that was the CCTV CPU regression) — safe at CCTV packet
|
|
1659
|
+
// rates.
|
|
1660
|
+
this.#adoptRemote(state, remote.address, remote.port);
|
|
1683
1661
|
if (!state.lastUdpRecvMs) {
|
|
1684
1662
|
this.#debugLog(`udp_confirmed friend=${friendId} via=${remote.address}:${remote.port} (direct UDP path live)`);
|
|
1685
1663
|
}
|
|
@@ -3146,7 +3124,7 @@ export class Peer {
|
|
|
3146
3124
|
};
|
|
3147
3125
|
this.#friendSessions.set(friendId, session);
|
|
3148
3126
|
}
|
|
3149
|
-
session
|
|
3127
|
+
this.#adoptRemote(session, host, port);
|
|
3150
3128
|
this.#rememberEndpointCandidate(session, host, port);
|
|
3151
3129
|
if (realPublicKey && !session.friendRealPublicKey) {
|
|
3152
3130
|
session.friendRealPublicKey = realPublicKey;
|
|
@@ -3155,6 +3133,22 @@ export class Peer {
|
|
|
3155
3133
|
session.friendDhtPublicKey = dhtPublicKey;
|
|
3156
3134
|
}
|
|
3157
3135
|
}
|
|
3136
|
+
/** Single choke point for setting session.remote (the direct-UDP send
|
|
3137
|
+
* endpoint). Never downgrades off a LOCKED physical-LAN path to a non-LAN
|
|
3138
|
+
* endpoint (public srflx / Tailscale-exit hairpin): the LAN lock
|
|
3139
|
+
* (session.lanRemoteHost) is decided at candidate-learn / maintenance time —
|
|
3140
|
+
* the only places allowed the getPhysicalLanSubnets() syscall — so this guard
|
|
3141
|
+
* is just a string compare and is safe to call from the per-packet hot path.
|
|
3142
|
+
* Replacing the per-packet getPhysicalLanSubnets() call here was the fix for
|
|
3143
|
+
* the CCTV CPU regression. */
|
|
3144
|
+
#adoptRemote(session, host, port) {
|
|
3145
|
+
if (session.lanRemoteHost &&
|
|
3146
|
+
session.remote?.host === session.lanRemoteHost &&
|
|
3147
|
+
host !== session.lanRemoteHost) {
|
|
3148
|
+
return; // stay locked on the physical-LAN path
|
|
3149
|
+
}
|
|
3150
|
+
session.remote = { host, port };
|
|
3151
|
+
}
|
|
3158
3152
|
#rememberEndpointCandidate(session, host, port) {
|
|
3159
3153
|
const now = Date.now();
|
|
3160
3154
|
const next = (session.endpointCandidates ?? []).filter((candidate) => !(candidate.host === host && candidate.port === port));
|
|
@@ -3499,7 +3493,7 @@ export class Peer {
|
|
|
3499
3493
|
const haveLanCandidate = (session.endpointCandidates ?? []).some((c) => isPrivateAddress(c.host) && !isCgnatAddress(c.host) &&
|
|
3500
3494
|
getPhysicalLanSubnets().some((s) => isInIpv4Subnet(c.host, s)));
|
|
3501
3495
|
if (!haveRealUdp && !haveLanCandidate) {
|
|
3502
|
-
session
|
|
3496
|
+
this.#adoptRemote(session, host, port);
|
|
3503
3497
|
}
|
|
3504
3498
|
// Nudge a keepalive out immediately so the upgrade doesn't wait for
|
|
3505
3499
|
// the next periodic ALIVE — fans out over UDP (punched) + TCP.
|
|
@@ -3684,7 +3678,7 @@ export class Peer {
|
|
|
3684
3678
|
if (tcpAvailable)
|
|
3685
3679
|
session.hasTcpRoute = true;
|
|
3686
3680
|
if (connectCandidates.length > 0) {
|
|
3687
|
-
session.
|
|
3681
|
+
this.#adoptRemote(session, connectCandidates[0].host, connectCandidates[0].port);
|
|
3688
3682
|
const endpointKey = `${connectCandidates[0].host}:${connectCandidates[0].port}`;
|
|
3689
3683
|
if (this.#lastEndpointSelectedKey.get(friendId) !== endpointKey) {
|
|
3690
3684
|
this.#debugLog(`endpoint_selected friend=${friendId} endpoint=${endpointKey}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/peer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.69",
|
|
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",
|