summaryrefslogtreecommitdiffstats
path: root/python-client/tcprelay.py
diff options
context:
space:
mode:
Diffstat (limited to 'python-client/tcprelay.py')
-rw-r--r--python-client/tcprelay.py146
1 files changed, 146 insertions, 0 deletions
diff --git a/python-client/tcprelay.py b/python-client/tcprelay.py
new file mode 100644
index 0000000..3075fcb
--- /dev/null
+++ b/python-client/tcprelay.py
@@ -0,0 +1,146 @@
+#!/usr/bin/python
+#
+# tcprelay.py - TCP connection relay for usbmuxd
+#
+# Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 or version 3.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import usbmux
+import SocketServer
+import select
+from optparse import OptionParser
+import sys
+import threading
+
+class SocketRelay(object):
+ def __init__(self, a, b, maxbuf=65535):
+ self.a = a
+ self.b = b
+ self.atob = ""
+ self.btoa = ""
+ self.maxbuf = maxbuf
+ def handle(self):
+ while True:
+ rlist = []
+ wlist = []
+ xlist = [self.a, self.b]
+ if self.atob:
+ wlist.append(self.b)
+ if self.btoa:
+ wlist.append(self.a)
+ if len(self.atob) < self.maxbuf:
+ rlist.append(self.a)
+ if len(self.btoa) < self.maxbuf:
+ rlist.append(self.b)
+ rlo, wlo, xlo = select.select(rlist, wlist, xlist)
+ if xlo:
+ return
+ if self.a in wlo:
+ n = self.a.send(self.btoa)
+ self.btoa = self.btoa[n:]
+ if self.b in wlo:
+ n = self.b.send(self.atob)
+ self.atob = self.atob[n:]
+ if self.a in rlo:
+ s = self.a.recv(self.maxbuf - len(self.atob))
+ if not s:
+ return
+ self.atob += s
+ if self.b in rlo:
+ s = self.b.recv(self.maxbuf - len(self.btoa))
+ if not s:
+ return
+ self.btoa += s
+ #print "Relay iter: %8d atob, %8d btoa, lists: %r %r %r"%(len(self.atob), len(self.btoa), rlo, wlo, xlo)
+
+class TCPRelay(SocketServer.BaseRequestHandler):
+ def handle(self):
+ print "Incoming connection to %d"%self.server.server_address[1]
+ mux = usbmux.USBMux("/tmp/usbmuxd")
+ print "Waiting for devices..."
+ if not mux.devices:
+ mux.process(1.0)
+ if not mux.devices:
+ print "No device found"
+ self.request.close()
+ return
+ dev = mux.devices[0]
+ print "Connecting to device %s"%str(dev)
+ dsock = mux.connect(dev, self.server.rport)
+ lsock = self.request
+ print "Connection established, relaying data"
+ try:
+ fwd = SocketRelay(dsock, lsock, self.server.bufsize * 1024)
+ fwd.handle()
+ finally:
+ dsock.close()
+ lsock.close()
+ print "Connection closed"
+
+class TCPServer(SocketServer.TCPServer):
+ allow_reuse_address = True
+
+class ThreadedTCPServer(SocketServer.ThreadingMixIn, TCPServer):
+ pass
+
+HOST = "localhost"
+
+parser = OptionParser(usage="usage: %prog [OPTIONS] RemotePort[:LocalPort] [RemotePort[:LocalPort]]...")
+parser.add_option("-t", "--threaded", dest='threaded', action='store_true', default=False, help="use threading to handle multiple connections at once")
+parser.add_option("-b", "--bufsize", dest='bufsize', action='store', metavar='KILOBYTES', type='int', default=128, help="specify buffer size for socket forwarding")
+
+options, args = parser.parse_args()
+
+serverclass = TCPServer
+if options.threaded:
+ serverclass = ThreadedTCPServer
+
+if len(args) == 0:
+ parser.print_help()
+ sys.exit(1)
+
+ports = []
+
+for arg in args:
+ try:
+ if ':' in arg:
+ rport, lport = arg.split(":")
+ rport = int(rport)
+ lport = int(lport)
+ ports.append((rport, lport))
+ else:
+ ports.append((int(arg), int(arg)))
+ except:
+ parser.print_help()
+ sys.exit(1)
+
+servers=[]
+
+for rport, lport in ports:
+ print "Forwarding local port %d to remote port %d"%(lport, rport)
+ server = serverclass((HOST, lport), TCPRelay)
+ server.rport = rport
+ server.bufsize = options.bufsize
+ servers.append(server)
+
+alive = True
+
+while alive:
+ try:
+ rl, wl, xl = select.select(servers, [], [])
+ for server in rl:
+ server.handle_request()
+ except:
+ alive = False