from socket import * from thread import start_new_thread from Queue import Queue, Empty from time import time ALLOW_NONLOCAL_CONNECT = False TIMEOUT = 120.0 MAX_CONNEXIONS = 15 class Connexion: def __init__(self, s): self.s = s self.activity() self.inqueue = Queue() self.outqueue = Queue() start_new_thread(self.reader_thread, ()) start_new_thread(self.writer_thread, ()) def __del__(self): if hasattr(self, 'outqueue'): self.outqueue.put(None) def activity(self): self.timeout = time() + TIMEOUT def reader_thread(self): try: while True: self.inqueue.put(self.s.recv(4096)) except error: print "Closed reader_thread()" def writer_thread(self): try: while True: item = self.outqueue.get() if item is None: break self.s.sendall(item) except error: print "Closed writer_thread()" def read(self, timeout): timeout = float(timeout) result = [] try: if timeout > 0: data = self.inqueue.get(timeout=timeout) else: data = self.inqueue.get(block=False) result.append(data) # try to get more data until the queue is exhausted while True: result.append(self.inqueue.get(block=False)) except Empty: pass self.activity() data = ''.join(result) return data.encode('base64') connexions = {} class Denied(Exception): pass def handle_request(path): now = time() if not path.startswith('/'): raise Denied, path k = path[1:].split('/', 4) if len(k) <= 1: #data = "\n" #contenttype = "text/plain" raise Denied, path else: # k[0] is an arbitrary timestamp try: handler = globals()['CMD_' + k[1]] except KeyError: raise Denied, path data = 'cHs2' + handler(*k[2:]) contenttype = "application/octet-stream" for key, c in connexions.items(): if now > c.timeout: print "Timing out %s!" % (key,) CMD_close(key) return data, contenttype def CMD_connect(key, host, port): assert len(connexions) < MAX_CONNEXIONS if not ALLOW_NONLOCAL_CONNECT: assert host in ('127.0.0.1', 'localhost') port = int(port) s = socket(AF_INET, SOCK_STREAM) s.connect((host, port)) connexions[key] = Connexion(s) return ":-) connect\n" ## def CMD_w(key, ignored, data): ## c = connexions[key] ## data += '='*((-len(data))&3) ## print repr(data) ## c.outqueue.put(data.decode('base64')) ## c.activity() ## return ':-) w\n' def CMD_r(key, timeout): c = connexions[key] return c.read(timeout) def CMD_wr(key, timeout, data): c = connexions[key] data += '='*((-len(data))&3) c.outqueue.put(data.decode('base64')) return c.read(timeout) def CMD_close(key): c = connexions.pop(key) c.s.close() return '.'