PeSIT server restart appends data: recovery point computed with the configured interval, and a fresh request for a known transfer resumes it
Summary
When a PeSIT server transfer is interrupted (gateway process killed during a reception) and the peer restarts it, the file received is corrupt and the transfer is reported DONE. Measured on a real peer restarting on its own after the interruption: 30 408 704 bytes received for a 20 971 520-byte file, wrong checksum, status DONE. Setting disableRestart on the server changes nothing (24 117 248 bytes).
What the wire shows
- First CREATE, synchronisation points 1, 2, 3…; the gateway dies at 10 248 192 bytes.
- The peer restarts with PI 15 = 1. The gateway answers ACK(WRITE) with PI 18 = 9:
transferHandler.StartDataTransfercomputes the recovery point asProgress / t.conf.CheckpointSize— the configured interval (1 MiB here) — whereas the interval negotiated with the peer (PI 7) is 36 KiB. The gateway then seeks to 9 MiB; for the peer, point 9 means 331 KiB. - The restart fails; the peer tries again without PI 15 (a fresh request, same transfer id). The gateway finds its interrupted transfer, does no repositioning (not a restart) and appends the whole file after the 9 MiB already there:
9 437 184 + 20 971 520 = 30 408 704.
The in-session restart callback (restartReceived, F.RESYN) has the same defect in another form: checkpointSize = 1 // TODO, so the file is repositioned at the point number in bytes, and the point answered to the peer is that byte offset.
Fix
- the recovery point and the byte offset use the interval negotiated for the transfer (
ServerTransfer.CheckpointSize()), not the configured one; without checkpoints the transfer starts over; - a request that is not a restart, for a transfer already known, repositions the file at its beginning;
-
restartReceiveduses the negotiated interval and answers the point actually reached.
Test
TestRecoveryPointUsesTheNegotiatedInterval (unit). Measured on the real peer after the fix: the interrupted reception restarted by the peer ends with a bit-identical file (see the merge request).
Related: lib/pesitlib/pesit#51 reported the symptom on the library side; the cause is in the application.