55import threading
66import time
77import asyncio
8+ import xml .etree .ElementTree as ET
89
910from . import log
1011
@@ -103,13 +104,17 @@ def __init__(self, input_stream=None):
103104 """
104105 self .__sock = None
105106 self .input_stream = input_stream
107+ self .proxy_success = False
106108
107- def start (self , host = '' , port = 9000 , timeout = 30 ):
109+ def start (self , host = '' , proxy_host = '' , proxy_port = 9001 , idekey = None , port = 9000 , timeout = 30 ):
108110 """Listen for a connection from the debugger. Listening for the actual
109111 connection is handled by self.listen()
110112
111113 host -- host name where debugger is running (default '')
112114 port -- port number which debugger is listening on (default 9000)
115+ proxy_host -- If using a DBGp Proxy, host name where the proxy is running (default None to disable)
116+ proxy_port -- If using a DBGp Proxy, port where the proxy is listening for debugger connections (default 9001)
117+ idekey -- The idekey that our Api() wrapper is expecting. Only required if using a proxy
113118 timeout -- time in seconds to wait for a debugger connection before giving up (default 30)
114119 """
115120 print ('Waiting for a connection (Ctrl-C to cancel, this message will '
@@ -120,13 +125,17 @@ def start(self, host='', port=9000, timeout=30):
120125 serv .setblocking (1 )
121126 serv .bind ((host , port ))
122127 serv .listen (5 )
123- self .__sock = self .listen (serv , timeout )
128+ if proxy_host and proxy_port :
129+ # Register ourselves with the proxy server
130+ self .proxyinit (proxy_host , proxy_port , port , idekey )
131+ self .__sock = self .accept (serv , timeout )
124132 except socket .timeout :
125133 raise TimeoutError ("Timeout waiting for connection" )
126134 finally :
135+ self .proxystop (proxy_host , proxy_port , idekey )
127136 serv .close ()
128137
129- def listen (self , serv , timeout ):
138+ def accept (self , serv , timeout ):
130139 """Non-blocking listener. Provides support for keyboard interrupts from
131140 the user. Although it's non-blocking, the user interface will still
132141 block until the timeout is reached.
@@ -155,13 +164,50 @@ def socket(self):
155164 def has_socket (self ):
156165 return self .__sock is not None
157166
167+ def proxyinit (self , proxy_host , proxy_port , port , idekey ):
168+ """Register ourselves with the proxy."""
169+ if not proxy_host or not proxy_port :
170+ return
171+
172+ self .log ("Connecting to DBGp proxy [%s:%d]" % (proxy_host , proxy_port ))
173+ proxy_conn = socket .create_connection ((proxy_host , proxy_port ), 30 )
174+
175+ self .log ("Sending proxyinit command" )
176+ msg = 'proxyinit -p %d -k %s -m 0' % (port , idekey )
177+ proxy_conn .send (msg .encode ())
178+ proxy_conn .shutdown (socket .SHUT_WR )
179+
180+ # Parse proxy response
181+ response = proxy_conn .recv (8192 )
182+ proxy_conn .close ()
183+ response = ET .fromstring (response )
184+ self .proxy_success = bool (response .get ("success" ))
185+
186+ def proxystop (self , proxy_host , proxy_port , idekey ):
187+ """De-register ourselves from the proxy."""
188+ if not self .proxy_success :
189+ return
190+
191+ proxy_conn = socket .create_connection ((proxy_host , proxy_port ), 30 )
192+
193+ self .log ("Sending proxystop command" )
194+ msg = 'proxystop -k %s' % str (idekey )
195+ proxy_conn .send (msg .encode ())
196+ proxy_conn .close ()
197+ self .proxy_success = False
198+
199+
158200
159201class BackgroundSocketCreator (threading .Thread ):
160202
161- def __init__ (self , host , port , output_q ):
203+ def __init__ (self , host , port , proxy_host , proxy_port , idekey , output_q ):
162204 self .__output_q = output_q
163205 self .__host = host
164206 self .__port = port
207+ self .__proxy_host = proxy_host
208+ self .__proxy_port = proxy_port
209+ self .__idekey = idekey
210+ self .proxy_success = False
165211 self .__socket_task = None
166212 self .__loop = None
167213 threading .Thread .__init__ (self )
@@ -189,6 +235,9 @@ async def run_async(self):
189235 try :
190236 # using ensure_future here since before 3.7, this is not a coroutine, but returns a future
191237 self .__socket_task = asyncio .ensure_future (self .__loop .sock_accept (s ))
238+ if self .__proxy_host and self .__proxy_port :
239+ # Register ourselves with the proxy server
240+ await self .proxyinit ()
192241 client , address = await self .__socket_task
193242 # set resulting socket to blocking
194243 client .setblocking (True )
@@ -197,6 +246,7 @@ async def run_async(self):
197246 self .__output_q .put ((client , address ))
198247 break
199248 except socket .error :
249+ await self .proxystop ()
200250 # No connection
201251 pass
202252 except socket .error as socket_error :
@@ -214,9 +264,44 @@ async def run_async(self):
214264 self .log ("Error: %s" % str (sys .exc_info ()))
215265 self .log ("Stopping server" )
216266 finally :
267+ await self .proxystop ()
217268 self .log ("Finishing socket server" )
218269 s .close ()
219270
271+ async def proxyinit (self ):
272+ """Register ourselves with the proxy."""
273+ if not self .__proxy_host or not self .__proxy_port :
274+ return
275+
276+ self .log ("Connecting to DBGp proxy [%s:%d]" % (self .__proxy_host , self .__proxy_port ))
277+ proxy_conn = socket .create_connection ((self .__proxy_host , self .__proxy_port ), 30 )
278+
279+ self .log ("Sending proxyinit command" )
280+ msg = 'proxyinit -p %d -k %s -m 0' % (self .__port , self .__idekey )
281+ proxy_conn .send (msg .encode ())
282+ proxy_conn .shutdown (socket .SHUT_WR )
283+
284+ # Parse proxy response
285+ response = proxy_conn .recv (8192 )
286+ proxy_conn .close ()
287+ response = ET .fromstring (response )
288+ self .proxy_success = bool (response .get ("success" ))
289+
290+ async def proxystop (self ):
291+ """De-register ourselves from the proxy."""
292+ if not self .proxy_success :
293+ return
294+
295+ proxy_conn = socket .create_connection ((self .__proxy_host , self .__proxy_port ), 30 )
296+
297+ self .log ("Sending proxystop command" )
298+ msg = 'proxystop -k %s' % str (self .__idekey )
299+ proxy_conn .send (msg .encode ())
300+ proxy_conn .close ()
301+ self .proxy_success = False
302+
303+
304+
220305 def _exit (self ):
221306 if self .__socket_task :
222307 # this will raise asyncio.CancelledError
@@ -236,10 +321,10 @@ def __init__(self):
236321 def __del__ (self ):
237322 self .stop ()
238323
239- def start (self , host , port ):
324+ def start (self , host , port , proxy_host , proxy_port , ide_key ):
240325 if not self .is_alive ():
241326 self .__thread = BackgroundSocketCreator (
242- host , port , self .__socket_q )
327+ host , port , proxy_host , proxy_port , ide_key , self .__socket_q )
243328 self .__thread .start ()
244329
245330 def is_alive (self ):
0 commit comments