@decentnetwork/peer 0.1.47 → 0.1.49
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 +42 -13
- package/package.json +1 -1
package/dist/peer.js
CHANGED
|
@@ -9,7 +9,7 @@ import { PACKET_TYPE_MESSAGE, PACKET_TYPE_FRIEND_REQUEST, PACKET_TYPE_USERINFO,
|
|
|
9
9
|
import { NET_PACKET_ONION_ANNOUNCE_RESPONSE, NET_PACKET_ONION_DATA_RESPONSE, ONION_FRIEND_REQUEST_ID, createOnionAnnounceRequest, createOnionDataPacket, createOnionDataRequest, createOnionRequest0, openOnionAnnounceResponse, openOnionDataPacket, openOnionDataResponse } from "./compat/tox-onion.js";
|
|
10
10
|
import { CRYPTO_PACKET_DHTPK, CRYPTO_PACKET_FRIEND_REQ, NET_PACKET_CRYPTO, createToxDhtCryptoRequest, openToxDhtCryptoRequest } from "./compat/tox-dht-crypto.js";
|
|
11
11
|
import { NET_PACKET_PING_REQUEST, NET_PACKET_PING_RESPONSE, NET_PACKET_GET_NODES, NET_PACKET_SEND_NODES, encodeDhtRpc, decodeDhtRpc, buildPingPlain, parsePingPlain, buildGetNodesPlain, parseGetNodesPlain, buildSendNodesPlain, parseSendNodesNodeBytes, packUdpNodeV4 } from "./compat/dht-rpc.js";
|
|
12
|
-
import { FileTransferManager } from "./compat/filetransfer.js";
|
|
12
|
+
import { FileTransferManager, PACKET_ID_FILE_SENDREQUEST, PACKET_ID_FILE_CONTROL, PACKET_ID_FILE_DATA } from "./compat/filetransfer.js";
|
|
13
13
|
import { NET_PACKET_CRYPTO_DATA, NET_PACKET_CRYPTO_HS, NET_PACKET_COOKIE_REQUEST, NET_PACKET_COOKIE_RESPONSE, createCookieRequest, createCookieResponse, createCryptoDataPacket, createCryptoHandshake, openCookieRequest, openCookieResponse, openCryptoDataPacket, openCryptoHandshake, incrementNonce } from "./compat/net-crypto.js";
|
|
14
14
|
import { LegacyExpressClient } from "./compat/express.js";
|
|
15
15
|
import { TcpRelayPool } from "./compat/tcp-relay-pool.js";
|
|
@@ -1551,14 +1551,26 @@ export class Peer {
|
|
|
1551
1551
|
if (!opened) {
|
|
1552
1552
|
continue;
|
|
1553
1553
|
}
|
|
1554
|
-
// De-duplicate. The dual-send path
|
|
1555
|
-
// BOTH
|
|
1556
|
-
// without this guard
|
|
1557
|
-
//
|
|
1558
|
-
//
|
|
1559
|
-
//
|
|
1560
|
-
//
|
|
1561
|
-
|
|
1554
|
+
// De-duplicate — but ONLY for dual-sent channels. The dual-send path
|
|
1555
|
+
// delivers a lossless packet over BOTH UDP and relay with the SAME
|
|
1556
|
+
// packet number, so without this guard a chat message is dispatched
|
|
1557
|
+
// (stored / shown) twice. Drop anything at or below the receive
|
|
1558
|
+
// low-water mark, like toxcore net_crypto drops below buffer_start.
|
|
1559
|
+
//
|
|
1560
|
+
// EXCEPT single-transport channels (bulk IP = bulkDataPacketId, and
|
|
1561
|
+
// file transfer 80-82): they are NOT dual-sent, so they never produce
|
|
1562
|
+
// duplicates — and the low-water mark would then only drop a
|
|
1563
|
+
// legitimately REORDERED packet, which over a high-rate stream (CCTV
|
|
1564
|
+
// over a long-haul China↔US path that reorders) is pure added loss /
|
|
1565
|
+
// jitter. IP forwarding is order-independent (the TUN/TCP above
|
|
1566
|
+
// reassembles), so deliver every packet. Must run BEFORE the nonce
|
|
1567
|
+
// advance so a real duplicate doesn't desync the receive nonce.
|
|
1568
|
+
const innerKind = opened.payload.length > 0 ? opened.payload[0] : -1;
|
|
1569
|
+
const isSingleTransportKind = (this.#opts.bulkDataPacketId !== undefined && innerKind === this.#opts.bulkDataPacketId) ||
|
|
1570
|
+
innerKind === PACKET_ID_FILE_SENDREQUEST ||
|
|
1571
|
+
innerKind === PACKET_ID_FILE_CONTROL ||
|
|
1572
|
+
innerKind === PACKET_ID_FILE_DATA;
|
|
1573
|
+
if (!isSingleTransportKind && opened.packetNumber < (state.receiveBufferStart ?? 0)) {
|
|
1562
1574
|
continue;
|
|
1563
1575
|
}
|
|
1564
1576
|
state.peerBaseNonce[state.peerBaseNonce.length - 2] = packet[1];
|
|
@@ -2785,8 +2797,23 @@ export class Peer {
|
|
|
2785
2797
|
// e.g. decentlan IP=163) stays bulk / single-transport to avoid the relay
|
|
2786
2798
|
// backlog + duplicate fan-out that high packet rates cause. Chat is sparse
|
|
2787
2799
|
// and net_crypto dedups by packet number, so dual-send is safe here.
|
|
2788
|
-
|
|
2789
|
-
|
|
2800
|
+
// File transfer (80 sendrequest / 81 control / 82 data) is ALSO treated as
|
|
2801
|
+
// bulk → single-transport. It is high-volume AND order-sensitive: the
|
|
2802
|
+
// receiver reassembles chunks SEQUENTIALLY (position is implicit) and there
|
|
2803
|
+
// is no retransmit queue. Dual-sending it over UDP + relay (two paths with
|
|
2804
|
+
// different latency) reorders the chunks, and the receive-side low-water
|
|
2805
|
+
// dedup then drops the late copies — so a large file (mp4) gets gaps /
|
|
2806
|
+
// wrong order and never completes, while a tiny one (png, 1-2 chunks)
|
|
2807
|
+
// happens to finish before reordering bites. Pinning file transfer to a
|
|
2808
|
+
// single transport keeps the chunks in send order. (Reliability across a
|
|
2809
|
+
// lossy path still wants a reorder buffer + retransmit — tracked separately.)
|
|
2810
|
+
const isFileTransfer = kind === PACKET_ID_FILE_SENDREQUEST || kind === PACKET_ID_FILE_CONTROL || kind === PACKET_ID_FILE_DATA;
|
|
2811
|
+
const isBulkData = (this.#opts.bulkDataPacketId !== undefined && kind === this.#opts.bulkDataPacketId) || isFileTransfer;
|
|
2812
|
+
// File transfer rides the relay RELIABLY (never dropped under backpressure):
|
|
2813
|
+
// a dropped IP/CCTV packet is fine (the stream moves on), but a dropped file
|
|
2814
|
+
// chunk corrupts the file (no retransmit). So bulk IP data stays droppable
|
|
2815
|
+
// while file transfer is queued.
|
|
2816
|
+
await this.#sendToFriend(friendId, encrypted, session, isBulkData, isFileTransfer);
|
|
2790
2817
|
}
|
|
2791
2818
|
/**
|
|
2792
2819
|
* Send `packet` to `friendId` over whichever transport(s) are
|
|
@@ -2796,7 +2823,7 @@ export class Peer {
|
|
|
2796
2823
|
* receiving end (toxcore does the same when both transports are up).
|
|
2797
2824
|
* Throws only if zero transports succeeded.
|
|
2798
2825
|
*/
|
|
2799
|
-
async #sendToFriend(friendId, packet, session, isBulkData = false) {
|
|
2826
|
+
async #sendToFriend(friendId, packet, session, isBulkData = false, reliableOnRelay = false) {
|
|
2800
2827
|
const s = session ?? this.#friendSessions.get(friendId);
|
|
2801
2828
|
let udpOk = false;
|
|
2802
2829
|
let tcpOk = false;
|
|
@@ -2876,7 +2903,9 @@ export class Peer {
|
|
|
2876
2903
|
// Bulk IP data is droppable over the relay: under backpressure the
|
|
2877
2904
|
// relay client drops it (bounded queue) rather than buffering seconds
|
|
2878
2905
|
// of packets. Control frames pass isBulkData=false and always queue.
|
|
2879
|
-
|
|
2906
|
+
// File transfer is bulk (single-transport routing) but must NOT be
|
|
2907
|
+
// dropped — a lost chunk corrupts the file — so it is queued reliably.
|
|
2908
|
+
const sent = this.#tcpRelays.sendToFriend(tcpKey, packet, isBulkData && !reliableOnRelay);
|
|
2880
2909
|
if (sent > 0) {
|
|
2881
2910
|
tcpOk = true;
|
|
2882
2911
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/peer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.49",
|
|
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",
|