Skip to content

Commit 402357f

Browse files
Merge pull request #511 from aleixq/master
Add dbgpproxy support
2 parents 3f3b131 + 6efc0ae commit 402357f

3 files changed

Lines changed: 100 additions & 7 deletions

File tree

‎plugin/vdebug.vim‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ let g:vdebug_options_defaults = {
7979
\ 'port' : 9000,
8080
\ 'timeout' : 20,
8181
\ 'server' : '',
82+
\ "proxy_host" : '',
83+
\ "proxy_port" : 9001,
8284
\ 'on_close' : 'stop',
8385
\ 'break_on_open' : 1,
8486
\ 'ide_key' : '',

‎python3/vdebug/connection.py‎

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import threading
66
import time
77
import asyncio
8+
import xml.etree.ElementTree as ET
89

910
from . 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

159201
class 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):

‎python3/vdebug/listener.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ def __init__(self):
2222
def start(self):
2323
self.__server.start(opts.Options.get('server'),
2424
opts.Options.get('port', int),
25+
opts.Options.get('proxy_host'),
26+
opts.Options.get('proxy_port', int),
27+
opts.Options.get('ide_key'),
2528
opts.Options.get('timeout', int))
2629

2730
def stop(self):
@@ -51,7 +54,10 @@ def start(self):
5154
if opts.Options.get("auto_start", int):
5255
vim.command('autocmd Vdebug CursorHold,CursorHoldI,CursorMoved,CursorMovedI,FocusGained,FocusLost * python3 debugger.start_if_ready()')
5356
self.__server.start(opts.Options.get('server'),
54-
opts.Options.get('port', int))
57+
opts.Options.get('port', int),
58+
opts.Options.get('proxy_host'),
59+
opts.Options.get('proxy_port', int),
60+
opts.Options.get('ide_key'))
5561

5662
def stop(self):
5763
if opts.Options.get("auto_start", bool):

0 commit comments

Comments
 (0)