diff options
author | Avery Pennarun <apenwarr@gmail.com> | 2011-01-26 02:34:12 -0800 |
---|---|---|
committer | Avery Pennarun <apenwarr@gmail.com> | 2011-01-26 02:34:46 -0800 |
commit | b570778894045d0ae461368d071e86ba4e82415a (patch) | |
tree | b4df5fd398e3efd3dafdc2c62fa735334b9bac80 | |
parent | 4c5185dc55fb1f141da8657eadcf07f207d42fab (diff) |
dns: trim DNS channel handlers after a response, or after a timeout.
This avoids memory/socket leaks.
-rw-r--r-- | client.py | 21 | ||||
-rw-r--r-- | server.py | 15 |
2 files changed, 25 insertions, 11 deletions
@@ -1,4 +1,4 @@ -import struct, socket, select, errno, re, signal +import struct, socket, select, errno, re, signal, time import compat.ssubprocess as ssubprocess import helpers, ssnet, ssh, ssyslog from ssnet import SockWrapper, Handler, Proxy, Mux, MuxWrapper @@ -293,22 +293,27 @@ def _main(listener, fw, ssh_cmd, remotename, python, latency_control, handlers.append(Proxy(SockWrapper(sock, sock), outwrap)) handlers.append(Handler([listener], onaccept)) - dnspeers = {} + dnsreqs = {} def dns_done(chan, data): - peer = dnspeers.get(chan) - debug1('dns_done: channel=%r peer=%r\n' % (chan, peer)) + peer,timeout = dnsreqs.get(chan) + debug3('dns_done: channel=%r peer=%r\n' % (chan, peer)) if peer: - del dnspeers[chan] - debug1('doing sendto %r\n' % (peer,)) + del dnsreqs[chan] + debug3('doing sendto %r\n' % (peer,)) dnslistener.sendto(data, peer) def ondns(): pkt,peer = dnslistener.recvfrom(4096) + now = time.time() if pkt: - debug1('Got DNS request from %r: %d bytes\n' % (peer, len(pkt))) + debug1('DNS request from %r: %d bytes\n' % (peer, len(pkt))) chan = mux.next_channel() - dnspeers[chan] = peer + dnsreqs[chan] = peer,now+30 mux.send(chan, ssnet.CMD_DNS_REQ, pkt) mux.channels[chan] = lambda cmd,data: dns_done(chan,data) + for chan,(peer,timeout) in dnsreqs.items(): + if timeout < now: + del dnsreqs[chan] + debug3('Remaining DNS requests: %d\n' % len(dnsreqs)) if dnslistener: handlers.append(Handler([dnslistener], ondns)) @@ -1,4 +1,4 @@ -import re, struct, socket, select, traceback +import re, struct, socket, select, traceback, time if not globals().get('skip_imports'): import ssnet, helpers, hostwatch import compat.ssubprocess as ssubprocess @@ -111,6 +111,7 @@ class DnsProxy(Handler): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) Handler.__init__(self, [sock]) self.sock = sock + self.timeout = time.time()+30 self.mux = mux self.chan = chan self.sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42) @@ -119,8 +120,9 @@ class DnsProxy(Handler): def callback(self): data = self.sock.recv(4096) - debug2('dns response: %d bytes\n' % len(data)) + debug2('DNS response: %d bytes\n' % len(data)) self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data) + self.ok = False def main(): @@ -184,7 +186,7 @@ def main(): dnshandlers = {} def dns_req(channel, data): - debug1('got dns request!\n') + debug2('Incoming DNS request.\n') h = DnsProxy(mux, channel, data) handlers.append(h) dnshandlers[channel] = h @@ -201,3 +203,10 @@ def main(): if latency_control: mux.check_fullness() mux.callback() + + if dnshandlers: + now = time.time() + for channel,h in dnshandlers.items(): + if h.timeout < now or not h.ok: + del dnshandlers[channel] + h.ok = False |