Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.vscode/

__pycache__/

.DS_Store
30 changes: 27 additions & 3 deletions driver/connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
from pymobiledevice3.cli.remote import select_device, RemoteServiceDiscoveryService
from pymobiledevice3.cli.remote import start_tunnel
from pymobiledevice3.cli.remote import verify_tunnel_imports
from pymobiledevice3.remote.core_device_tunnel_service import TunnelProtocol

from pymobiledevice3.services.amfi import AmfiService

from pymobiledevice3.exceptions import NoDeviceConnectedError

logger = logging.getLogger(__name__)

def get_usbmux_lockdownclient():
while True:
try:
Expand Down Expand Up @@ -50,6 +53,27 @@ def get_serverrsd():


async def tunnel(rsd: RemoteServiceDiscoveryService, queue: multiprocessing.Queue):
async with start_tunnel(rsd, None) as tunnel_result:
queue.put((tunnel_result.address, tunnel_result.port))
await tunnel_result.client.wait_closed()
tunnel_errors = []
protocols = (TunnelProtocol.QUIC, TunnelProtocol.TCP)

for protocol in protocols:
try:
logger.info("starting %s tunnel", protocol.value)
async with start_tunnel(rsd, None, protocol=protocol) as tunnel_result:
logger.info("tunnel established with %s", protocol.value)
queue.put({
"status": "ok",
"address": tunnel_result.address,
"port": tunnel_result.port,
"protocol": protocol.value,
})
await tunnel_result.client.wait_closed()
return
except Exception as exc:
logger.warning("failed to start %s tunnel: %s", protocol.value, exc)
tunnel_errors.append(f"{protocol.value}: {exc!r}")

raise ConnectionError(
"Unable to establish tunnel. "
f"Tried protocols: {', '.join(tunnel_errors)}"
)
28 changes: 22 additions & 6 deletions init/tunnel.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
import asyncio
import multiprocessing
from queue import Empty

from driver import connect

def tunnel_proc(queue: multiprocessing.Queue):
server_rsd = connect.get_serverrsd()
asyncio.run(connect.tunnel(server_rsd, queue))
try:
server_rsd = connect.get_serverrsd()
asyncio.run(connect.tunnel(server_rsd, queue))
except Exception as exc:
queue.put({
"status": "error",
"error": repr(exc),
})


def tunnel():
# start the tunnel in another process
queue = multiprocessing.Queue()
process = multiprocessing.Process(target=tunnel_proc, args=(queue,))
process.start()

# get the address and port of the tunnel
address, port = queue.get()

return process, address, port
while True:
try:
result = queue.get(timeout=1)
except Empty:
if not process.is_alive():
raise RuntimeError("Tunnel process exited before returning connection info")
continue

if result.get("status") == "ok":
return process, result["address"], result["port"]

process.join(timeout=1)
raise RuntimeError(f"Tunnel setup failed: {result.get('error', 'unknown error')}")
12 changes: 9 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,14 @@ def main():
# start the tunnel in another process
logger.info("starting tunnel")
original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
process, address, port = tunnel.tunnel()
signal.signal(signal.SIGINT, original_sigint_handler)
try:
process, address, port = tunnel.tunnel()
except RuntimeError as exc:
logger.error("failed to start tunnel: %s", exc)
print(f"启动隧道失败:{exc}")
return
finally:
signal.signal(signal.SIGINT, original_sigint_handler)
logger.info("tunnel started")
try:
logger.debug(f"tunnel address: {address}, port: {port}")
Expand Down Expand Up @@ -90,4 +96,4 @@ def main():


if __name__ == "__main__":
main()
main()