fix: register file-done channel before sending file-accept
For small files, file-done arrives before wireFileRecv's goroutine reaches the pendingDones registration — the message was discarded and the goroutine timed out. Fix by registering doneCh in AcceptOffer (before sending file-accept), carrying it through recvState, and reading it in wireFileRecv without re-registering. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user