@decentnetwork/peer 0.1.1 → 0.1.3

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.
Files changed (2) hide show
  1. package/dist/peer.js +81 -0
  2. package/package.json +1 -1
package/dist/peer.js CHANGED
@@ -2030,6 +2030,87 @@ export class Peer {
2030
2030
  if (session.remote && friend.status !== "online") {
2031
2031
  this.#setFriendOnline(friendId, session.remote.host, session.remote.port);
2032
2032
  }
2033
+ // Phase 1.2: keep retrying UDP holepunch even after the session
2034
+ // is already "established" via TCP relay. The toxcore-derived
2035
+ // logic above stops trying once anybody is reachable, which is
2036
+ // correct for messaging (text gets through) but disastrous for
2037
+ // IP-packet forwarding (latency stays at ~500-1500ms via the
2038
+ // relay detour instead of dropping to ~80ms once UDP works).
2039
+ //
2040
+ // We detect "on TCP-relay only" as: session.hasTcpRoute is set
2041
+ // AND session.remote is either null or the synthetic
2042
+ // {host: "tcp:<dhtpk>", port: 0} placeholder. In that state we
2043
+ // re-send our DHT-PK so the peer (re-)learns our UDP endpoint,
2044
+ // re-discover their endpoint via DHT, and trigger a fresh
2045
+ // #initiateSession that will send a UDP cookie request. If UDP
2046
+ // succeeds, #handleCryptoHandshake overwrites session.remote
2047
+ // with the real endpoint and #sendMessengerPacket picks UDP
2048
+ // over TCP from then on. Throttled to UDP_RETRY_INTERVAL_MS so
2049
+ // the loop's 250ms tick doesn't flood DHT lookups.
2050
+ const realUdpRemote = session.remote &&
2051
+ !session.remote.host?.startsWith("tcp:") &&
2052
+ session.remote.port !== 0;
2053
+ if (!realUdpRemote && session.hasTcpRoute) {
2054
+ const UDP_RETRY_INTERVAL_MS = 15_000;
2055
+ const lastTry = session.lastUdpRetryMs ?? 0;
2056
+ if (now - lastTry > UDP_RETRY_INTERVAL_MS) {
2057
+ session.lastUdpRetryMs = now;
2058
+ // Recompute friend's real public key for the DHT-PK push.
2059
+ // Same fallback chain as the cooldown branch below.
2060
+ let friendRealPk = session.friendRealPublicKey;
2061
+ if (!friendRealPk && friend.address) {
2062
+ try {
2063
+ friendRealPk = parseCarrierAddress(friend.address).publicKey;
2064
+ }
2065
+ catch {
2066
+ // Fall through to the userid form.
2067
+ }
2068
+ }
2069
+ if (!friendRealPk && friend.pubkey) {
2070
+ try {
2071
+ friendRealPk = base58ToBytes(friend.pubkey);
2072
+ }
2073
+ catch {
2074
+ // Ignore malformed.
2075
+ }
2076
+ }
2077
+ if (friendRealPk && friendRealPk.length === 32) {
2078
+ // 1. Re-announce our DHT-PK so peer learns *our* UDP endpoint
2079
+ // even if their own DHT lookup against us was stale.
2080
+ void this.#sendOnionDhtPk(friendRealPk).catch((error) => {
2081
+ this.#debugLog(`UDP retry: dhtpk_send for ${friendId} failed: ${error.message}`);
2082
+ });
2083
+ // 2. Try to discover the peer's UDP endpoint and kick a
2084
+ // fresh cookie request via UDP. discoverAndCacheFriend
2085
+ // Endpoint accepts EITHER the DHT-PK (preferred —
2086
+ // direct DHT lookup) OR the friend's real identity
2087
+ // public key (onion-routed lookup). When the session
2088
+ // came up via TCP-relay only, neither side has
2089
+ // received an onion DHT-PK from the other yet, so
2090
+ // session.friendDhtPublicKey is null. Falling back
2091
+ // to friendRealPk keeps the retry from being a no-op
2092
+ // in exactly the case it was designed to fix.
2093
+ const dhtPk = session.friendDhtPublicKey;
2094
+ const searchKey = dhtPk ?? friendRealPk;
2095
+ if (searchKey && searchKey.length === 32) {
2096
+ void this.#discoverAndCacheFriendEndpoint(friendId, searchKey)
2097
+ .then((found) => {
2098
+ if (found) {
2099
+ return this.#initiateSession(friendId).catch(() => undefined);
2100
+ }
2101
+ })
2102
+ .catch(() => undefined);
2103
+ }
2104
+ // Always also retry initiate if we have a cached real
2105
+ // UDP endpoint — covers the case where discovery
2106
+ // succeeded earlier but the cookie request was lost.
2107
+ if (friend.remoteHost && friend.remotePort) {
2108
+ void this.#initiateSession(friendId).catch(() => undefined);
2109
+ }
2110
+ this.#debugLog(`UDP retry attempt for ${friendId} (currently on TCP relay, search=${dhtPk ? "dht-pk" : "real-pk"})`);
2111
+ }
2112
+ }
2113
+ }
2033
2114
  continue;
2034
2115
  }
2035
2116
  // No active session: tell the friend our DHT public key so they can
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
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",