@decentnetwork/peer 0.1.129 → 0.1.131
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 -2
- package/package.json +1 -1
package/dist/peer.js
CHANGED
|
@@ -968,7 +968,7 @@ export class Peer {
|
|
|
968
968
|
uint32ToLe(friendAddress.nospam),
|
|
969
969
|
appPayload
|
|
970
970
|
]);
|
|
971
|
-
const routes = await this.#discoverFriendRoutes(friendAddress.publicKey);
|
|
971
|
+
const routes = await this.#discoverFriendRoutes(friendAddress.publicKey, true);
|
|
972
972
|
this.#debugLog(`friend route discovery done routes=${routes.length}`);
|
|
973
973
|
if (routes.length === 0) {
|
|
974
974
|
// The direct net_crypto send needs a known endpoint for the target; to
|
|
@@ -2928,10 +2928,35 @@ export class Peer {
|
|
|
2928
2928
|
// Ignore invalid offline payloads.
|
|
2929
2929
|
}
|
|
2930
2930
|
}
|
|
2931
|
-
|
|
2931
|
+
/**
|
|
2932
|
+
* @param userInitiated skips the budget. Adding a friend must not wait on a
|
|
2933
|
+
* throttle meant for background upkeep.
|
|
2934
|
+
*/
|
|
2935
|
+
async #discoverFriendRoutes(friendPublicKey, userInitiated = false) {
|
|
2932
2936
|
if (!this.#keyPair) {
|
|
2933
2937
|
throw new Error("Peer is not started");
|
|
2934
2938
|
}
|
|
2939
|
+
// Same per-friend budget as #discoverAndCacheFriendEndpoint, enforced HERE
|
|
2940
|
+
// for the same reason: this is the THIRD time today the cost simply moved
|
|
2941
|
+
// to whichever caller was not gated. #sendOnionDhtPk's call sites were
|
|
2942
|
+
// throttled, so the sweep underneath them became the top crypto entry
|
|
2943
|
+
// instead — 17.9% of wall on gfax, climbing (20% -> 27% over ten minutes)
|
|
2944
|
+
// rather than settling, because the DHT-PK path kept a FLAT 25s interval
|
|
2945
|
+
// while the endpoint path had already been given backoff.
|
|
2946
|
+
//
|
|
2947
|
+
// A gate inside the function cannot be bypassed by a call site added later.
|
|
2948
|
+
const routeKey = `routes:${carrierIdFromPublicKey(friendPublicKey)}`;
|
|
2949
|
+
if (!userInitiated) {
|
|
2950
|
+
const misses = this.#onionLookupMisses.get(routeKey) ?? 0;
|
|
2951
|
+
const budget = Math.min(DHT_PK_ANNOUNCE_COOLDOWN_MS * Math.max(1, misses), ONION_LOOKUP_MAX_BACKOFF_MS);
|
|
2952
|
+
const since = Date.now() - (this.#onionLookupCooldown.get(routeKey) ?? 0);
|
|
2953
|
+
if (since < budget) {
|
|
2954
|
+
this.#debugLog(`route discovery for ${routeKey} skipped: ${Math.round(since / 1000)}s ` +
|
|
2955
|
+
`since last (budget ${Math.round(budget / 1000)}s, misses ${misses})`);
|
|
2956
|
+
return [];
|
|
2957
|
+
}
|
|
2958
|
+
this.#onionLookupCooldown.set(routeKey, Date.now());
|
|
2959
|
+
}
|
|
2935
2960
|
const searchKey = createEphemeralKeyPair();
|
|
2936
2961
|
const routes = [];
|
|
2937
2962
|
const routeSeen = new Set();
|
|
@@ -3075,6 +3100,15 @@ export class Peer {
|
|
|
3075
3100
|
}
|
|
3076
3101
|
}
|
|
3077
3102
|
}
|
|
3103
|
+
// Miss accounting drives the backoff above. Without it the budget stays at
|
|
3104
|
+
// its 25s floor forever and the gate does nothing for the friends that
|
|
3105
|
+
// actually cost us — the ones that never resolve.
|
|
3106
|
+
if (!userInitiated) {
|
|
3107
|
+
if (routes.length > 0)
|
|
3108
|
+
this.#onionLookupMisses.delete(routeKey);
|
|
3109
|
+
else
|
|
3110
|
+
this.#onionLookupMisses.set(routeKey, (this.#onionLookupMisses.get(routeKey) ?? 0) + 1);
|
|
3111
|
+
}
|
|
3078
3112
|
return routes;
|
|
3079
3113
|
}
|
|
3080
3114
|
async #discoverAndCacheFriendEndpoint(friendId, searchPublicKey) {
|
|
@@ -4821,6 +4855,26 @@ export class Peer {
|
|
|
4821
4855
|
if (this.#isUnroutableSelfSource(host, port, observed)) {
|
|
4822
4856
|
return;
|
|
4823
4857
|
}
|
|
4858
|
+
// An ADVERTISED private address is only usable if we are on that network.
|
|
4859
|
+
//
|
|
4860
|
+
// Same provenance rule as the self-address check above, one step wider: a
|
|
4861
|
+
// packet that ARRIVED from a private address proves the path exists, but a
|
|
4862
|
+
// peer merely listing one proves nothing — RFC1918 ranges are reused
|
|
4863
|
+
// everywhere. Seen in the field between tokyo (Japan) and a laptop at home:
|
|
4864
|
+
// tokyo adopted 10.0.0.245, an address that only means anything inside that
|
|
4865
|
+
// house, and sent every IP packet there. Friend online, session
|
|
4866
|
+
// established, transport "both", ping 100% loss.
|
|
4867
|
+
//
|
|
4868
|
+
// Only reached for advertised candidates, so the cached-but-not-free
|
|
4869
|
+
// getPhysicalLanSubnets() stays off the per-packet path (see the CCTV CPU
|
|
4870
|
+
// regression note on #isUnroutableSelfSource).
|
|
4871
|
+
if (!observed &&
|
|
4872
|
+
isPrivateAddress(host) &&
|
|
4873
|
+
!isCgnatAddress(host) &&
|
|
4874
|
+
!getPhysicalLanSubnets().some((sub) => isInIpv4Subnet(host, sub))) {
|
|
4875
|
+
this.#debugLog(`ignoring advertised private endpoint ${host}:${port} — not on any of our LANs`);
|
|
4876
|
+
return;
|
|
4877
|
+
}
|
|
4824
4878
|
if (session.lanRemoteHost &&
|
|
4825
4879
|
session.remote?.host === session.lanRemoteHost &&
|
|
4826
4880
|
host !== session.lanRemoteHost &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/peer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.131",
|
|
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",
|