From 07a2837a100c5e83832faebe466c85c1d0af8066 Mon Sep 17 00:00:00 2001 From: Ben Shaya Date: Fri, 28 Aug 2026 20:24:52 +0000 Subject: [PATCH] Suppport IPv6 and dual-stack ADB server connections in ppadb When forwarding the ADB server port (5037) through SSH tunnels or on IPv6-enabled hosts (e.g., Rodete), the daemon binds to IPv6 loopback (`::1:5037`). ppadb previously hardcoded `socket.AF_INET` (IPv4 only) and `127.0.0.1`, which caused connection attempts to fail with `[Errno 111] Connection refused`. This change: - Updates `ppadb.connection.Connection.connect()` to resolve the host via `socket.getaddrinfo()`, supporting both IPv6 and IPv4 sockets. - Updates default `Client` host to `'localhost'`. --- ppadb/client.py | 2 +- ppadb/connection.py | 45 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/ppadb/client.py b/ppadb/client.py index 45b108c..c4d964b 100644 --- a/ppadb/client.py +++ b/ppadb/client.py @@ -5,7 +5,7 @@ logger = AdbLogging.get_logger(__name__) class Client(Host): - def __init__(self, host='127.0.0.1', port=5037): + def __init__(self, host='localhost', port=5037): self.host = host self.port = port diff --git a/ppadb/connection.py b/ppadb/connection.py index eca32bd..581d564 100644 --- a/ppadb/connection.py +++ b/ppadb/connection.py @@ -23,23 +23,46 @@ def __exit__(self, type, value, traceback): def connect(self): logger.debug("Connect to adb server - {}:{}".format(self.host, self.port)) - self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - l_onoff = 1 - l_linger = 0 - - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', l_onoff, l_linger)) - if self.timeout: - self.socket.settimeout(self.timeout) - + err = None + connected = False try: - self.socket.connect((self.host, self.port)) + addr_list = socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM) except socket.error as e: - self.close() raise RuntimeError("ERROR: connecting to {}:{} {}.\nIs adb running on your computer?".format( self.host, self.port, e + )) from e + + for af, socktype, proto, _, sa in addr_list: + try: + self.socket = socket.socket(af, socktype, proto) + except socket.error as e: + err = e + self.socket = None + continue + + l_onoff = 1 + l_linger = 0 + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', l_onoff, l_linger)) + if self.timeout: + self.socket.settimeout(self.timeout) + + try: + self.socket.connect(sa) + connected = True + break + except socket.error as e: + err = e + self.close() + + if not connected: + if self.socket is None and err is not None: + raise err + raise RuntimeError("ERROR: connecting to {}:{} {}.\nIs adb running on your computer?".format( + self.host, + self.port, + err )) return self.socket