@@ -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
4951func (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
8084func (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+
152175type 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