@@ -28,6 +28,7 @@ func (t *Tunnel) handleUDP(l *cio.Logger, rwc io.ReadWriteCloser, hostPort strin
28
28
},
29
29
udpConns : conns ,
30
30
maxMTU : settings .EnvInt ("UDP_MAX_SIZE" , 9012 ),
31
+ maxConns : settings .EnvInt ("UDP_MAX_CONNS" , 100 ),
31
32
}
32
33
h .Debugf ("UDP max size: %d bytes" , h .maxMTU )
33
34
for {
@@ -43,7 +44,8 @@ type udpHandler struct {
43
44
hostPort string
44
45
* udpChannel
45
46
* udpConns
46
- maxMTU int
47
+ maxMTU int
48
+ maxConns int
47
49
}
48
50
49
51
func (h * udpHandler ) handleWrite (p * udpPacket ) error {
@@ -62,12 +64,14 @@ func (h *udpHandler) handleWrite(p *udpPacket) error {
62
64
//TODO++ dont use go-routines, switch to pollable
63
65
// array of listeners where all listeners are
64
66
// sweeped periodically, removing the idle ones
65
- const maxConns = 100
67
+
66
68
if ! exists {
67
- if h .udpConns .len () <= maxConns {
69
+ if h .udpConns .len () <= h . maxConns {
68
70
go h .handleRead (p , conn )
69
71
} 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 )
71
75
}
72
76
}
73
77
_ , err = conn .Write (p .Payload )
@@ -79,7 +83,14 @@ func (h *udpHandler) handleWrite(p *udpPacket) error {
79
83
80
84
func (h * udpHandler ) handleRead (p * udpPacket , conn * udpConn ) {
81
85
//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
+ }
83
94
buff := make ([]byte , h .maxMTU )
84
95
for {
85
96
//response must arrive within 15 seconds
@@ -149,7 +160,35 @@ func (cs *udpConns) closeAll() {
149
160
cs .Unlock ()
150
161
}
151
162
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
+
152
175
type udpConn struct {
153
176
id string
154
177
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 ()
155
194
}
0 commit comments