Skip to content

Commit 4387baf

Browse files
committed
fix: fix the udpConns map does not release new conns when its length is over 100 (jpillora#515)
1 parent 64ce945 commit 4387baf

File tree

1 file changed

+44
-5
lines changed

1 file changed

+44
-5
lines changed

share/tunnel/tunnel_out_ssh_udp.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func (t *Tunnel) handleUDP(l *cio.Logger, rwc io.ReadWriteCloser, hostPort strin
2828
},
2929
udpConns: conns,
3030
maxMTU: settings.EnvInt("UDP_MAX_SIZE", 9012),
31+
maxConns: settings.EnvInt("UDP_MAX_CONNS", 100),
3132
}
3233
h.Debugf("UDP max size: %d bytes", h.maxMTU)
3334
for {
@@ -43,7 +44,8 @@ type udpHandler struct {
4344
hostPort string
4445
*udpChannel
4546
*udpConns
46-
maxMTU int
47+
maxMTU int
48+
maxConns int
4749
}
4850

4951
func (h *udpHandler) handleWrite(p *udpPacket) error {
@@ -62,12 +64,14 @@ func (h *udpHandler) handleWrite(p *udpPacket) error {
6264
//TODO++ dont use go-routines, switch to pollable
6365
// array of listeners where all listeners are
6466
// sweeped periodically, removing the idle ones
65-
const maxConns = 100
67+
6668
if !exists {
67-
if h.udpConns.len() <= maxConns {
69+
if h.udpConns.len() <= h.maxConns {
6870
go h.handleRead(p, conn)
6971
} else {
70-
h.Debugf("exceeded max udp connections (%d)", maxConns)
72+
//write only
73+
h.udpConns.setCleanUpTimer(conn.id)
74+
h.Debugf("exceeded max udp connections (%d)", h.maxConns)
7175
}
7276
}
7377
_, err = conn.Write(p.Payload)
@@ -79,7 +83,14 @@ func (h *udpHandler) handleWrite(p *udpPacket) error {
7983

8084
func (h *udpHandler) handleRead(p *udpPacket, conn *udpConn) {
8185
//ensure connection is cleaned up
82-
defer h.udpConns.remove(conn.id)
86+
defer func() {
87+
h.udpConns.remove(conn.id)
88+
conn.Close()
89+
}()
90+
if h.udpConns.len() > h.maxConns {
91+
h.Debugf("exceeded max udp connections (%d)", h.maxConns)
92+
return
93+
}
8394
buff := make([]byte, h.maxMTU)
8495
for {
8596
//response must arrive within 15 seconds
@@ -149,7 +160,35 @@ func (cs *udpConns) closeAll() {
149160
cs.Unlock()
150161
}
151162

163+
func (cs *udpConns) setCleanUpTimer(id string) {
164+
cs.Lock()
165+
defer cs.Unlock()
166+
conn, ok := cs.m[id]
167+
if ok {
168+
conn.writeTimer = time.AfterFunc(settings.EnvDuration("UDP_DEADLINE", 15*time.Second), func() {
169+
cs.remove(conn.id)
170+
conn.Close()
171+
})
172+
}
173+
}
174+
152175
type udpConn struct {
153176
id string
154177
net.Conn
178+
writeTimer *time.Timer
179+
}
180+
181+
func (w *udpConn) Write(b []byte) (int, error) {
182+
if w.writeTimer != nil {
183+
w.writeTimer.Stop()
184+
w.writeTimer.Reset(settings.EnvDuration("UDP_DEADLINE", 15*time.Second))
185+
}
186+
return w.Conn.Write(b)
187+
}
188+
189+
func (w *udpConn) Close() error {
190+
if w.writeTimer != nil {
191+
w.writeTimer.Stop()
192+
}
193+
return w.Conn.Close()
155194
}

0 commit comments

Comments
 (0)