diff --git a/cli/internal/transport/transport.go b/cli/internal/transport/transport.go index b8f3c5e..aaff774 100644 --- a/cli/internal/transport/transport.go +++ b/cli/internal/transport/transport.go @@ -777,13 +777,20 @@ func (s *Session) AcceptOffer(offer FileOffer, downloadDir string) { if info, err := os.Stat(partPath); err == nil && info.Size() < offer.Size { offset = info.Size() } - s.controlSend(map[string]string{"type": "file-accept", "xid": offer.XID, "offset": fmt.Sprint(offset)}) + // Register doneCh before sending file-accept so file-done can never arrive + // before the channel exists (small files finish before wireFileRecv runs). + doneCh := make(chan string, 1) s.mu.Lock() + if s.pendingDones == nil { + s.pendingDones = make(map[string]chan string) + } + s.pendingDones[offer.XID] = doneCh if s.pendingRecvs == nil { s.pendingRecvs = make(map[string]*recvState) } - s.pendingRecvs[offer.XID] = &recvState{offer: offer, dir: downloadDir, have: offset} + s.pendingRecvs[offer.XID] = &recvState{offer: offer, dir: downloadDir, have: offset, doneCh: doneCh} s.mu.Unlock() + s.controlSend(map[string]string{"type": "file-accept", "xid": offer.XID, "offset": fmt.Sprint(offset)}) } func (s *Session) RejectOffer(xid string) { @@ -791,10 +798,11 @@ func (s *Session) RejectOffer(xid string) { } type recvState struct { - offer FileOffer - dir string - have int64 - f *os.File + offer FileOffer + dir string + have int64 + f *os.File + doneCh chan string } func (s *Session) wireFileRecv(dc *webrtc.DataChannel) { @@ -885,13 +893,9 @@ func (s *Session) wireFileRecv(dc *webrtc.DataChannel) { } // ยง9: wait for file-done and verify sha256 before reporting success. - doneCh := make(chan string, 1) - s.mu.Lock() - if s.pendingDones == nil { - s.pendingDones = make(map[string]chan string) - } - s.pendingDones[xid] = doneCh - s.mu.Unlock() + // doneCh was registered in AcceptOffer before file-accept was sent, + // so file-done can never arrive before the channel exists. + doneCh := rs.doneCh var expectedSHA256 string select { case expectedSHA256 = <-doneCh: