#! /usr/bin/python import getopt, socket, SocketServer, threading, sys __version__ = "0.2" def show_version(): print 'mm v'+__version__+', by Rimon Barr:', print 'Network middle-man.' def show_usage(): show_version() print print 'Usage: mm [--listen=] :' print ' mm -h | -v' print print ' -h, -?, --help display this help information' print ' -v, --version display version' print ' --listen= set listen port' print print 'Send comments, suggestions and bug reports to .' def usage_error(): print 'mm: command syntax error' print 'Try `mm --help\' for more information.' def parse_hostport(s): try: host, port = s.split(':') except TypeError: 'expect string of format -- host:port' return host, int(port) def logpipe(fin, fout, flog, label=''): if not label: label = fin try: c = fin.read(1) while c: fout.write(c); fout.flush() flog.write(c, label) c = fin.read(1) except IOError: pass fout.close() class multilog(object): def __init__(self, fout): self.__fout, self.__src, self.__buf = fout, None, '' def write(self, c, src): if src!=self.__src: self.flush(); self.__src=src self.__buf += c def flush(self): if self.__buf: buf,self.__buf = ''.join(['\\x%02x'%ord(c) for c in self.__buf]),'' print >> self.__fout, "%s: '%s'" % (self.__src, buf) self.__fout.flush() def __del__(self): self.flush() def mm(): try: opts, args = getopt.getopt(sys.argv[1:], 'hv?', ['help', 'version', 'listen=']) except getopt.GetoptError, e: print e; usage_error(); return listenport = None # process options for o, a in opts: if o in ("-h", "--help", "-?"): show_usage(); return if o in ("-v", "--version"): show_version(); return if o in ('--listen'): listenport = int(a) if len(args)!=1: usage_error(); return host, port = parse_hostport(args[0]) if listenport is None: listenport = port lout = multilog(sys.stdout) # define server class mysrv(SocketServer.ThreadingTCPServer): allow_reuse_address = True daemon_threads = True # define connection handler class myconn(SocketServer.StreamRequestHandler): def handle(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host,port)) cin, cout = self.rfile, self.wfile sin, sout = s.makefile('r',1024), s.makefile('w',1024) tin = threading.Thread(target=logpipe, args=(cin,sout,lout,'C')) tout = threading.Thread(target=logpipe, args=(sin,cout,lout,'S')) tin.setDaemon(1); tin.start() tout.setDaemon(1); tout.start() tin.join(); tout.join() srv = mysrv(('',listenport), myconn) print 'Logging: localhost:%d <--> %s:%d' % (listenport,host,port) try: srv.socket.settimeout(1) while True: try: srv.handle_request() except KeyboardInterrupt: raise except: print >> sys.stderr, 'Error: %s' % fn.exceptionStr() except KeyboardInterrupt: pass lout.flush() srv, lout = None, None sys.exit(0) if __name__=='__main__': mm()