|
4 | 4 |
|
5 | 5 | SOCKET_TIMEOUT = 300 |
6 | 6 | PACKET_SIZE = 65536 |
| 7 | +UDP_LIMIT = 150 |
7 | 8 | DUMMY = lambda s: s |
8 | 9 |
|
9 | 10 | asyncio.StreamReader.read_ = lambda self: self.read(PACKET_SIZE) |
@@ -210,28 +211,35 @@ def __init__(prot, data): |
210 | 211 | self.udpmap[addr] = prot |
211 | 212 | prot.databuf = [data] |
212 | 213 | prot.transport = None |
| 214 | + prot.update = 0 |
213 | 215 | def connection_made(prot, transport): |
214 | 216 | prot.transport = transport |
215 | 217 | for data in prot.databuf: |
216 | 218 | transport.sendto(data) |
217 | 219 | prot.databuf.clear() |
| 220 | + prot.update = time.time() |
218 | 221 | def new_data_arrived(prot, data): |
219 | 222 | if prot.transport: |
220 | 223 | prot.transport.sendto(data) |
221 | 224 | else: |
222 | 225 | prot.databuf.append(data) |
| 226 | + prot.update = time.time() |
223 | 227 | def datagram_received(prot, data, addr): |
224 | 228 | data = self.cipher.datagram.decrypt(data) if self.cipher else data |
225 | 229 | data = self.rproto.udp_client(data) if not self.direct else data |
226 | 230 | reply(data) |
| 231 | + prot.update = time.time() |
227 | 232 | def connection_lost(prot, exc): |
228 | | - self.udpmap.pop(addr) |
| 233 | + self.udpmap.pop(addr, None) |
229 | 234 | if addr in self.udpmap: |
230 | 235 | self.udpmap[addr].new_data_arrived(data) |
231 | 236 | else: |
232 | 237 | if self.direct and host == 'tunnel': |
233 | 238 | raise Exception('Unknown tunnel endpoint') |
234 | 239 | self.connection_change(1) |
| 240 | + if len(self.udpmap) > UDP_LIMIT: |
| 241 | + min_addr = min(self.udpmap, key=lambda x: self.udpmap[x].update) |
| 242 | + self.udpmap.pop(min_addr).close() |
235 | 243 | prot = Protocol(data) |
236 | 244 | remote_addr = (host, port) if self.direct else (self.host_name, self.port) |
237 | 245 | await asyncio.get_event_loop().create_datagram_endpoint(lambda: prot, remote_addr=remote_addr) |
|
0 commit comments