diff --git a/cli/internal/transport/transport.go b/cli/internal/transport/transport.go index d5a12f3..b8f3c5e 100644 --- a/cli/internal/transport/transport.go +++ b/cli/internal/transport/transport.go @@ -758,11 +758,12 @@ func (s *Session) SendFile(path string) error { return err } } + // §9: send file-done before closing the file DC so the control channel + // is still reachable when the message is delivered. + s.controlSend(map[string]string{"type": "file-done", "xid": xid, "sha256": sha256hex}) if err := dc.Close(); err != nil { return err } - // §9: send file-done with the pre-computed hash so the receiver can verify. - s.controlSend(map[string]string{"type": "file-done", "xid": xid, "sha256": sha256hex}) return nil } diff --git a/pwa/src/transport/flit.ts b/pwa/src/transport/flit.ts index fa5ba67..c39694f 100644 --- a/pwa/src/transport/flit.ts +++ b/pwa/src/transport/flit.ts @@ -510,9 +510,10 @@ export class PeerConn { this.events.fileSendProgress?.({ peer: this.peerId, xid, name: file.name, sent: resumeOffset + localOffset, total: file.size }) await new Promise(r => setTimeout(r, 0)) } - dc.close() - // §9: send file-done with sha256 so receiver can verify integrity. + // §9: send file-done before closing the file DC so the control channel + // is still healthy when the message is dispatched. this._dc({ type: 'file-done', xid, sha256: hash }) + dc.close() this.events.fileSent?.({ peer: this.peerId, xid, name: file.name }) }