mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
The system tests have a number of minor formatting and structural issues that would be better to clean up sooner rather than later. This PR addresses nearly all of them.
152 lines
3.8 KiB
Python
152 lines
3.8 KiB
Python
from __future__ import absolute_import
|
|
|
|
from collections import namedtuple
|
|
import contextlib
|
|
import socket
|
|
|
|
import ptvsd.socket as _ptvsd
|
|
|
|
|
|
convert_eof = _ptvsd.convert_eof
|
|
|
|
|
|
def resolve_hostname():
|
|
hostname = socket.gethostname()
|
|
try:
|
|
return socket.gethostbyname(hostname)
|
|
except socket.gaierror:
|
|
addr = ('8.8.8.8', 80)
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
try:
|
|
sock.connect(addr)
|
|
return sock.getsockname()[0]
|
|
finally:
|
|
sock.close()
|
|
|
|
|
|
# TODO: Add timeouts to the functions.
|
|
|
|
def create_server(address):
|
|
"""Return a server socket after binding."""
|
|
return _ptvsd.create_server(*address)
|
|
|
|
|
|
def create_client():
|
|
"""Return a new (unconnected) client socket."""
|
|
return _ptvsd.create_client()
|
|
|
|
|
|
def connect(sock, address):
|
|
"""Return a client socket after connecting.
|
|
|
|
If address is None then it's a server, so it will wait for a
|
|
connection. Otherwise it will connect to the remote host.
|
|
"""
|
|
return _connect(sock, address)
|
|
|
|
|
|
def bind(address):
|
|
"""Return (connect, remote addr) for the given address.
|
|
|
|
"connect" is a function with no args that returns (client, server),
|
|
which are sockets. If the host is None then a server socket will
|
|
be created bound to localhost, and that server socket will be
|
|
returned from connect(). Otherwise a client socket is connected to
|
|
the remote address and None is returned from connect() for the
|
|
server.
|
|
"""
|
|
host, _ = address
|
|
if host is None:
|
|
sock = create_server(address)
|
|
server = sock
|
|
connect_to = None
|
|
remote = sock.getsockname()
|
|
else:
|
|
sock = create_client()
|
|
server = None
|
|
connect_to = address
|
|
remote = address
|
|
|
|
def connect():
|
|
client = _connect(sock, connect_to)
|
|
return client, server
|
|
return connect, remote
|
|
|
|
|
|
def recv_as_read(sock):
|
|
"""Return a wrapper ardoung sock.read that arises EOFError when closed."""
|
|
def read(numbytes, _recv=sock.recv):
|
|
with convert_eof():
|
|
return _recv(numbytes)
|
|
return read
|
|
|
|
|
|
def send_as_write(sock):
|
|
"""Return a wrapper ardoung sock.send that arises EOFError when closed."""
|
|
def write(data, _send=sock.send):
|
|
with convert_eof():
|
|
return _send(data)
|
|
return write
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def timeout(sock, timeout):
|
|
"""A context manager that sets a timeout on blocking socket ops."""
|
|
orig = sock.gettimeout()
|
|
sock.settimeout(timeout)
|
|
try:
|
|
yield
|
|
finally:
|
|
sock.settimeout(orig)
|
|
|
|
|
|
def close(sock):
|
|
"""Shutdown and close the socket."""
|
|
_ptvsd.close_socket(sock)
|
|
|
|
|
|
class Connection(namedtuple('Connection', 'client server')):
|
|
"""A wrapper around a client socket.
|
|
|
|
If a server socket is provided then it will be closed when the
|
|
client is closed.
|
|
"""
|
|
|
|
def __new__(cls, client, server=None):
|
|
self = super(Connection, cls).__new__(
|
|
cls,
|
|
client,
|
|
server,
|
|
)
|
|
return self
|
|
|
|
def send(self, *args, **kwargs):
|
|
return self.client.send(*args, **kwargs)
|
|
|
|
def recv(self, *args, **kwargs):
|
|
return self.client.recv(*args, **kwargs)
|
|
|
|
def makefile(self, *args, **kwargs):
|
|
return self.client.makefile(*args, **kwargs)
|
|
|
|
def shutdown(self, *args, **kwargs):
|
|
if self.server is not None:
|
|
_ptvsd.shut_down(self.server, *args, **kwargs)
|
|
_ptvsd.shut_down(self.client, *args, **kwargs)
|
|
|
|
def close(self):
|
|
if self.server is not None:
|
|
self.server.close()
|
|
self.client.close()
|
|
|
|
|
|
########################
|
|
# internal functions
|
|
|
|
def _connect(sock, address):
|
|
if address is None:
|
|
client, _ = sock.accept()
|
|
else:
|
|
sock.connect(address)
|
|
client = sock
|
|
return client
|