summaryrefslogtreecommitdiffstats
path: root/python-client/tcprelay.py
diff options
context:
space:
mode:
authorGravatar Hector Martin2009-05-05 01:40:22 +0200
committerGravatar Hector Martin2009-05-05 01:40:22 +0200
commitdce2546afadd9185b7e65f1db6b127d6293b178c (patch)
tree956f7d1adbba68ca2db4ce7d8740e10be8f5f53b /python-client/tcprelay.py
parent78577f36b4fd92b052300e0b4d3b369d45b40e67 (diff)
downloadusbmuxd-dce2546afadd9185b7e65f1db6b127d6293b178c.tar.gz
usbmuxd-dce2546afadd9185b7e65f1db6b127d6293b178c.tar.bz2
Add python stuff and patches
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 @@
1#!/usr/bin/python
2#
3# tcprelay.py - TCP connection relay for usbmuxd
4#
5# Copyright (C) 2009 Hector Martin "marcan" <hector@marcansoft.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 2 or version 3.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20import usbmux
21import SocketServer
22import select
23from optparse import OptionParser
24import sys
25import threading
26
27class SocketRelay(object):
28 def __init__(self, a, b, maxbuf=65535):
29 self.a = a
30 self.b = b
31 self.atob = ""
32 self.btoa = ""
33 self.maxbuf = maxbuf
34 def handle(self):
35 while True:
36 rlist = []
37 wlist = []
38 xlist = [self.a, self.b]
39 if self.atob:
40 wlist.append(self.b)
41 if self.btoa:
42 wlist.append(self.a)
43 if len(self.atob) < self.maxbuf:
44 rlist.append(self.a)
45 if len(self.btoa) < self.maxbuf:
46 rlist.append(self.b)
47 rlo, wlo, xlo = select.select(rlist, wlist, xlist)
48 if xlo:
49 return
50 if self.a in wlo:
51 n = self.a.send(self.btoa)
52 self.btoa = self.btoa[n:]
53 if self.b in wlo:
54 n = self.b.send(self.atob)
55 self.atob = self.atob[n:]
56 if self.a in rlo:
57 s = self.a.recv(self.maxbuf - len(self.atob))
58 if not s:
59 return
60 self.atob += s
61 if self.b in rlo:
62 s = self.b.recv(self.maxbuf - len(self.btoa))
63 if not s:
64 return
65 self.btoa += s
66 #print "Relay iter: %8d atob, %8d btoa, lists: %r %r %r"%(len(self.atob), len(self.btoa), rlo, wlo, xlo)
67
68class TCPRelay(SocketServer.BaseRequestHandler):
69 def handle(self):
70 print "Incoming connection to %d"%self.server.server_address[1]
71 mux = usbmux.USBMux("/tmp/usbmuxd")
72 print "Waiting for devices..."
73 if not mux.devices:
74 mux.process(1.0)
75 if not mux.devices:
76 print "No device found"
77 self.request.close()
78 return
79 dev = mux.devices[0]
80 print "Connecting to device %s"%str(dev)
81 dsock = mux.connect(dev, self.server.rport)
82 lsock = self.request
83 print "Connection established, relaying data"
84 try:
85 fwd = SocketRelay(dsock, lsock, self.server.bufsize * 1024)
86 fwd.handle()
87 finally:
88 dsock.close()
89 lsock.close()
90 print "Connection closed"
91
92class TCPServer(SocketServer.TCPServer):
93 allow_reuse_address = True
94
95class ThreadedTCPServer(SocketServer.ThreadingMixIn, TCPServer):
96 pass
97
98HOST = "localhost"
99
100parser = OptionParser(usage="usage: %prog [OPTIONS] RemotePort[:LocalPort] [RemotePort[:LocalPort]]...")
101parser.add_option("-t", "--threaded", dest='threaded', action='store_true', default=False, help="use threading to handle multiple connections at once")
102parser.add_option("-b", "--bufsize", dest='bufsize', action='store', metavar='KILOBYTES', type='int', default=128, help="specify buffer size for socket forwarding")
103
104options, args = parser.parse_args()
105
106serverclass = TCPServer
107if options.threaded:
108 serverclass = ThreadedTCPServer
109
110if len(args) == 0:
111 parser.print_help()
112 sys.exit(1)
113
114ports = []
115
116for arg in args:
117 try:
118 if ':' in arg:
119 rport, lport = arg.split(":")
120 rport = int(rport)
121 lport = int(lport)
122 ports.append((rport, lport))
123 else:
124 ports.append((int(arg), int(arg)))
125 except:
126 parser.print_help()
127 sys.exit(1)
128
129servers=[]
130
131for rport, lport in ports:
132 print "Forwarding local port %d to remote port %d"%(lport, rport)
133 server = serverclass((HOST, lport), TCPRelay)
134 server.rport = rport
135 server.bufsize = options.bufsize
136 servers.append(server)
137
138alive = True
139
140while alive:
141 try:
142 rl, wl, xl = select.select(servers, [], [])
143 for server in rl:
144 server.handle_request()
145 except:
146 alive = False