Fix Connection timeout
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"dragontcp/internal/cover"
|
||||
@@ -163,20 +164,29 @@ func (l *bpLane) single(mode byte, sid wire.SessionID, seq uint64, payload []byt
|
||||
var lastErr error
|
||||
for attempt := 0; attempt < 2; attempt++ {
|
||||
if err := l.ensureLocked(); err != nil {
|
||||
if isTransportTimeout(err) {
|
||||
return 0, nil, err
|
||||
}
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
reused := l.pc.requests > 0
|
||||
_ = l.pc.conn.SetDeadline(time.Now().Add(timeout))
|
||||
if err := writeBPRequest(l.pc.conn, mode, sid, seq, payload, downloadHint, l.coverProfile.HeaderMask, l.coverProfile.Clear); err != nil {
|
||||
lastErr = err
|
||||
l.transportFailureLocked(reused)
|
||||
if isTransportTimeout(err) {
|
||||
return 0, nil, err
|
||||
}
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
status, body, err := readBPResponse(l.pc.conn, sid, mode, seq, l.coverProfile.HeaderMask, l.coverProfile.Clear)
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
l.transportFailureLocked(reused)
|
||||
if isTransportTimeout(err) {
|
||||
return 0, nil, err
|
||||
}
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
l.pc.requests++
|
||||
@@ -222,14 +232,20 @@ func (l *bpLane) download(sid wire.SessionID, offset uint64, maxChunk, count int
|
||||
var lastErr error
|
||||
for attempt := 0; attempt < 2; attempt++ {
|
||||
if err := l.ensureLocked(); err != nil {
|
||||
if isTransportTimeout(err) {
|
||||
return nil, 0, err
|
||||
}
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
reused := l.pc.requests > 0
|
||||
_ = l.pc.conn.SetDeadline(time.Now().Add(timeout))
|
||||
if err := writeBPRequest(l.pc.conn, mode, sid, offset, payload, hint, l.coverProfile.HeaderMask, l.coverProfile.Clear); err != nil {
|
||||
lastErr = err
|
||||
l.transportFailureLocked(reused)
|
||||
if isTransportTimeout(err) {
|
||||
return nil, 0, err
|
||||
}
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -238,8 +254,11 @@ func (l *bpLane) download(sid wire.SessionID, offset uint64, maxChunk, count int
|
||||
for i := 0; i < responses; i++ {
|
||||
status, body, err := readBPResponse(l.pc.conn, sid, mode, offset, l.coverProfile.HeaderMask, l.coverProfile.Clear)
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
l.transportFailureLocked(reused)
|
||||
if isTransportTimeout(err) {
|
||||
return nil, 0, err
|
||||
}
|
||||
lastErr = err
|
||||
goto retry
|
||||
}
|
||||
lastStatus = status
|
||||
@@ -292,6 +311,7 @@ type bpConn struct {
|
||||
pipeline int
|
||||
|
||||
closeOnce sync.Once
|
||||
dead atomic.Bool
|
||||
}
|
||||
|
||||
func openBPTunnel(serverAddr, token, targetHost string, targetPort int, opts chunkClientOptions) (net.Conn, error) {
|
||||
@@ -385,6 +405,9 @@ func (c *bpConn) fillReadBuffer() error {
|
||||
if c.consumedOffset > c.lastAck {
|
||||
status, body, err := c.downloadLane.single(bpModeACK, c.sid, c.consumedOffset, nil, 0)
|
||||
if err != nil {
|
||||
if isTransportTimeout(err) {
|
||||
c.dead.Store(true)
|
||||
}
|
||||
return err
|
||||
}
|
||||
if status == wire.StatusError {
|
||||
@@ -402,6 +425,10 @@ func (c *bpConn) fillReadBuffer() error {
|
||||
}
|
||||
data, status, err := c.downloadLane.download(c.sid, c.downloadOffset, chunk, count)
|
||||
if err != nil {
|
||||
if isTransportTimeout(err) {
|
||||
c.dead.Store(true)
|
||||
return err
|
||||
}
|
||||
old, next := c.downSizer.FailureReason(chunk, err)
|
||||
if old == next && next == c.opts.minSize {
|
||||
return err
|
||||
@@ -462,6 +489,10 @@ func (c *bpConn) Write(p []byte) (int, error) {
|
||||
n := minInt(size, len(p))
|
||||
status, body, err := c.uploadLane.single(bpModeUpload, c.sid, c.upOffset+2, p[:n], 0)
|
||||
if err != nil {
|
||||
if isTransportTimeout(err) {
|
||||
c.dead.Store(true)
|
||||
return total, err
|
||||
}
|
||||
old, next := c.upSizer.FailureReason(size, err)
|
||||
if old == next && next == c.opts.minSize {
|
||||
return total, err
|
||||
@@ -485,7 +516,11 @@ func (c *bpConn) Write(p []byte) (int, error) {
|
||||
|
||||
func (c *bpConn) Close() error {
|
||||
c.closeOnce.Do(func() {
|
||||
_, _, _ = c.downloadLane.single(bpModeACK, c.sid, c.consumedOffset, bpCloseMagic[:], 0)
|
||||
// A timeout is a hard tunnel boundary. Do not create a fresh physical
|
||||
// connection only to close a session that has already been abandoned.
|
||||
if !c.dead.Load() {
|
||||
_, _, _ = c.downloadLane.single(bpModeACK, c.sid, c.consumedOffset, bpCloseMagic[:], 0)
|
||||
}
|
||||
c.uploadLane.Close()
|
||||
c.downloadLane.Close()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user