diff options
Diffstat (limited to 'python-client/tcprelay.py')
| -rw-r--r-- | python-client/tcprelay.py | 146 | 
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 | 
