Skip to content

Commit bbc2929

Browse files
committed
bugfix : fix the udpConns map does not release new conns when its length is over 100
jpillora#515
1 parent 3e4d7fd commit bbc2929

File tree

1 file changed

+43
-5
lines changed

1 file changed

+43
-5
lines changed

share/tunnel/tunnel_out_ssh_udp.go

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func (t *Tunnel) handleUDP(l *cio.Logger, rwc io.ReadWriteCloser, hostPort strin
3333
},
3434
udpConns: conns,
3535
maxMTU: settings.EnvInt("UDP_MAX_SIZE", 9012),
36+
maxConns: settings.EnvInt("UDP_MAX_CONNS", 100),
3637
}
3738
h.Debugf("UDP max size: %d bytes", h.maxMTU)
3839
for {
@@ -48,7 +49,8 @@ type udpHandler struct {
4849
hostPort string
4950
*udpChannel
5051
*udpConns
51-
maxMTU int
52+
maxMTU int
53+
maxConns int
5254
}
5355

5456
func (h *udpHandler) handleWrite(p *udpPacket) error {
@@ -67,12 +69,13 @@ func (h *udpHandler) handleWrite(p *udpPacket) error {
6769
//TODO++ dont use go-routines, switch to pollable
6870
// array of listeners where all listeners are
6971
// sweeped periodically, removing the idle ones
70-
const maxConns = 100
7172
if !exists {
72-
if h.udpConns.len() <= maxConns {
73+
if h.udpConns.len() <= h.maxConns {
7374
go h.handleRead(p, conn)
7475
} else {
75-
h.Debugf("exceeded max udp connections (%d)", maxConns)
76+
//write only
77+
h.udpConns.setCleanUpTimer(conn.id)
78+
h.Debugf("exceeded max udp connections (%d)", h.maxConns)
7679
}
7780
}
7881
_, err = conn.Write(p.Payload)
@@ -84,7 +87,14 @@ func (h *udpHandler) handleWrite(p *udpPacket) error {
8487

8588
func (h *udpHandler) handleRead(p *udpPacket, conn *udpConn) {
8689
//ensure connection is cleaned up
87-
defer h.udpConns.remove(conn.id)
90+
defer func() {
91+
h.udpConns.remove(conn.id)
92+
conn.Close()
93+
}()
94+
if h.udpConns.len() > h.maxConns {
95+
h.Debugf("exceeded max udp connections (%d)", h.maxConns)
96+
return
97+
}
8898
buff := make([]byte, h.maxMTU)
8999
for {
90100
//response must arrive within 15 seconds
@@ -154,9 +164,37 @@ func (cs *udpConns) closeAll() {
154164
cs.Unlock()
155165
}
156166

167+
func (cs *udpConns) setCleanUpTimer(id string) {
168+
cs.Lock()
169+
defer cs.Unlock()
170+
conn, ok := cs.m[id]
171+
if ok {
172+
conn.writeTimer = time.AfterFunc(settings.EnvDuration("UDP_DEADLINE", 15*time.Second), func() {
173+
cs.remove(conn.id)
174+
conn.Close()
175+
})
176+
}
177+
}
178+
157179
type udpConn struct {
158180
id string
159181
net.Conn
182+
writeTimer *time.Timer
183+
}
184+
185+
func (w *udpConn) Write(b []byte) (int, error) {
186+
if w.writeTimer != nil {
187+
w.writeTimer.Stop()
188+
w.writeTimer.Reset(settings.EnvDuration("UDP_DEADLINE", 15*time.Second))
189+
}
190+
return w.Conn.Write(b)
191+
}
192+
193+
func (w *udpConn) Close() error {
194+
if w.writeTimer != nil {
195+
w.writeTimer.Stop()
196+
}
197+
return w.Conn.Close()
160198
}
161199

162200
func (t *Tunnel) handleSocksUDP(l *cio.Logger, rwc io.ReadWriteCloser) error {

0 commit comments

Comments
 (0)