@@ -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
5456func (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
8588func (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+
157179type 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
162200func (t * Tunnel ) handleSocksUDP (l * cio.Logger , rwc io.ReadWriteCloser ) error {
0 commit comments