@decentnetwork/peer 0.1.77 → 0.1.79
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/compat/filetransfer.d.ts +1 -0
- package/dist/compat/filetransfer.js +31 -4
- package/dist/peer.d.ts +2 -0
- package/dist/peer.js +2 -0
- package/package.json +1 -1
|
@@ -54,6 +54,7 @@ export declare class FileTransferManager {
|
|
|
54
54
|
}): string | null;
|
|
55
55
|
accept(friendId: string, fileNumber: number): void;
|
|
56
56
|
cancel(friendId: string, fileNumber: number, isSending: boolean): void;
|
|
57
|
+
cancelByFileId(friendId: string, fileIdHex: string, isSending: boolean): boolean;
|
|
57
58
|
handlePacket(friendId: string, packetId: number, payload: Uint8Array): boolean;
|
|
58
59
|
clearFriend(friendId: string): void;
|
|
59
60
|
}
|
|
@@ -311,6 +311,20 @@ export class FileTransferManager {
|
|
|
311
311
|
else
|
|
312
312
|
this.#endRecv(friendId, fileNumber);
|
|
313
313
|
}
|
|
314
|
+
// Cancel by content fileId (hex) — the daemon/UI tracks transfers by fileId,
|
|
315
|
+
// not the internal fileNumber, so it can stop a specific in-flight transfer.
|
|
316
|
+
cancelByFileId(friendId, fileIdHex, isSending) {
|
|
317
|
+
const inner = (isSending ? this.#sending : this.#receiving).get(friendId);
|
|
318
|
+
if (!inner)
|
|
319
|
+
return false;
|
|
320
|
+
for (const [fileNumber, st] of inner) {
|
|
321
|
+
if (hex(st.fileId) === fileIdHex) {
|
|
322
|
+
this.cancel(friendId, fileNumber, isSending);
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
314
328
|
handlePacket(friendId, packetId, payload) {
|
|
315
329
|
if (packetId === PACKET_ID_FILE_SENDREQUEST) {
|
|
316
330
|
this.#onSendRequest(friendId, payload);
|
|
@@ -751,8 +765,7 @@ export class FileTransferManager {
|
|
|
751
765
|
// so a dup-ack burst can't storm). No window backoff: loss ≠ congestion.
|
|
752
766
|
st.lastResendMs = nowMs();
|
|
753
767
|
st.lastLossMs = nowMs(); // the path is lossy → turn adaptive FEC on
|
|
754
|
-
|
|
755
|
-
st.nextSend = st.acked;
|
|
768
|
+
this.#rewindRetransmit(st);
|
|
756
769
|
}
|
|
757
770
|
if (st.acked >= st.size) {
|
|
758
771
|
this.#completeSend(friendId, st);
|
|
@@ -760,6 +773,21 @@ export class FileTransferManager {
|
|
|
760
773
|
}
|
|
761
774
|
void this.#pump(friendId, st);
|
|
762
775
|
}
|
|
776
|
+
// Rewind for a go-back-N retransmit: move the send cursor back to the ack point
|
|
777
|
+
// AND rewind the FEC high-water mark so the re-sent blocks get FRESH parity.
|
|
778
|
+
// Without the parity rewind a lossy TAIL freezes forever — re-sending the
|
|
779
|
+
// region drops new chunks faster than it fills the old holes, and the receiver
|
|
780
|
+
// has no parity to recover them locally (parity was emitted once, long gone).
|
|
781
|
+
// Re-emitting parity lets the receiver FEC-recover the holes, so the tail
|
|
782
|
+
// converges instead of stalling at 93% (observed on 100 MB+ files).
|
|
783
|
+
#rewindRetransmit(st) {
|
|
784
|
+
if (st.nextSend > st.acked)
|
|
785
|
+
st.nextSend = st.acked;
|
|
786
|
+
const ackBlock = Math.floor(st.acked / MAX_FILE_DATA_SIZE / FEC_K);
|
|
787
|
+
if (ackBlock - 1 < st.parityHighBlock)
|
|
788
|
+
st.parityHighBlock = ackBlock - 1;
|
|
789
|
+
st.lastLossMs = nowMs(); // keep FEC ON so the re-emit actually fires
|
|
790
|
+
}
|
|
763
791
|
// Single send loop. Awaits each send so net_crypto / the UDP socket applies
|
|
764
792
|
// backpressure (fire-and-forget blasted the whole window into the macOS UDP
|
|
765
793
|
// buffer at once → systematic overflow/drops the retransmit couldn't dig out
|
|
@@ -803,8 +831,7 @@ export class FileTransferManager {
|
|
|
803
831
|
st.cwnd = Math.max(CWND_MIN_CHUNKS, Math.floor(st.cwnd / 2));
|
|
804
832
|
st.lastAckAdvanceMs = nowMs();
|
|
805
833
|
st.lastResendMs = nowMs();
|
|
806
|
-
|
|
807
|
-
st.nextSend = st.acked; // go-back-N
|
|
834
|
+
this.#rewindRetransmit(st); // go-back-N + re-emit tail parity
|
|
808
835
|
void this.#pump(friendId, st);
|
|
809
836
|
}, WATCHDOG_MS);
|
|
810
837
|
if (typeof st.timer.unref === "function")
|
package/dist/peer.d.ts
CHANGED
|
@@ -111,6 +111,8 @@ export declare class Peer {
|
|
|
111
111
|
acceptFile(userid: string, fileNumber: number): void;
|
|
112
112
|
/** Cancel a transfer (isSending = true if we're the sender). */
|
|
113
113
|
cancelFile(userid: string, fileNumber: number, isSending?: boolean): void;
|
|
114
|
+
/** Cancel an in-flight transfer by its content fileId (hex). Returns true if found. */
|
|
115
|
+
cancelFileById(userid: string, fileId: string, isSending?: boolean): boolean;
|
|
114
116
|
/** Incoming file offer: { friendId, fileNumber, fileId, name, size, kind }. */
|
|
115
117
|
onFile(cb: (offer: {
|
|
116
118
|
friendId: string;
|
package/dist/peer.js
CHANGED
|
@@ -1032,6 +1032,8 @@ export class Peer {
|
|
|
1032
1032
|
acceptFile(userid, fileNumber) { this.#fileTransfer.accept(userid, fileNumber); }
|
|
1033
1033
|
/** Cancel a transfer (isSending = true if we're the sender). */
|
|
1034
1034
|
cancelFile(userid, fileNumber, isSending = false) { this.#fileTransfer.cancel(userid, fileNumber, isSending); }
|
|
1035
|
+
/** Cancel an in-flight transfer by its content fileId (hex). Returns true if found. */
|
|
1036
|
+
cancelFileById(userid, fileId, isSending = false) { return this.#fileTransfer.cancelByFileId(userid, fileId, isSending); }
|
|
1035
1037
|
/** Incoming file offer: { friendId, fileNumber, fileId, name, size, kind }. */
|
|
1036
1038
|
onFile(cb) { this.#events.on("file-offer", cb); }
|
|
1037
1039
|
/** Transfer progress: { friendId, fileId, received, total, sending? }. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/peer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.79",
|
|
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",
|