Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
morellexf13 committed Nov 14, 2023
2 parents c6df450 + 62ce4ae commit fc29a50
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ If applicable, add logs including backtraces for the given error that help expla

**Additional context**
Add any other context about the problem here.

## For community
⬇️ **Please click the 👍 reaction instead of leaving a `+1` or 👍 comment**
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ A clear and concise description of any alternative solutions or features you've

**Additional context**
Add any other context or screenshots about the feature request here.

## For community
⬇️ **Please click the 👍 reaction instead of leaving a `+1` or 👍 comment**
16 changes: 10 additions & 6 deletions pymobiledevice3/cli/cli_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def wrapper(*args, **kwargs):
raise AccessDeniedError()
else:
func(*args, **kwargs)

return wrapper


Expand Down Expand Up @@ -205,16 +206,19 @@ def tunneld(self, ctx, param: str, udid: Optional[str] = None) -> Optional[Remot
try:
# Connect to the specified device
self.service_provider = [rsd for rsd in rsds if rsd.udid == udid][0]
return self.service_provider
except IndexError:
raise DeviceNotFoundError(udid)

if len(rsds) == 1:
rsd = rsds[0]
else:
rsd = prompt_device_list(rsds)
if len(rsds) == 1:
self.service_provider = rsds[0]
else:
self.service_provider = prompt_device_list(rsds)

for rsd in rsds:
if rsd == self.service_provider:
continue
rsd.close()

self.service_provider = rsd
return self.service_provider


Expand Down
6 changes: 6 additions & 0 deletions pymobiledevice3/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ class NoDeviceConnectedError(PyMobileDevice3Exception):
pass


class InterfaceIndexNotFoundError(PyMobileDevice3Exception):
def __init__(self, address: str):
super().__init__()
self.address = address


class DeviceNotFoundError(PyMobileDevice3Exception):
def __init__(self, udid: str):
super().__init__()
Expand Down
3 changes: 2 additions & 1 deletion pymobiledevice3/services/mobile_image_mounter.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ def auto_mount_developer(lockdown: LockdownServiceProvider, xcode: str = None, v
raise AlreadyMountedError()

if version is None:
version = lockdown.product_version
version = Version(lockdown.product_version)
version = f'{version.major}.{version.minor}'
image_dir = f'{xcode}/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/{version}'
image_path = f'{image_dir}/DeveloperDiskImage.dmg'
signature = f'{image_path}.signature'
Expand Down
31 changes: 30 additions & 1 deletion pymobiledevice3/tunneld.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import asyncio
import dataclasses
import logging
import os
import signal
from contextlib import suppress
from typing import Dict, Tuple

Expand All @@ -12,6 +14,7 @@
from zeroconf import IPVersion
from zeroconf.asyncio import AsyncZeroconf

from pymobiledevice3.exceptions import InterfaceIndexNotFoundError
from pymobiledevice3.remote.module_imports import start_quic_tunnel
from pymobiledevice3.remote.remote_service_discovery import RemoteServiceDiscoveryService
from pymobiledevice3.remote.utils import stop_remoted
Expand Down Expand Up @@ -54,6 +57,14 @@ async def close(self):
with suppress(asyncio.CancelledError):
await task

def clear(self) -> None:
""" Clear active tunnels """
for udid, tunnel in self.active_tunnels.items():
logger.info(f'Removing tunnel {tunnel.address}')
tunnel.rsd.close()
tunnel.task.cancel()
self.active_tunnels = {}

@staticmethod
async def handle_new_tunnel(tun: Tunnel) -> None:
""" Create new tunnel """
Expand Down Expand Up @@ -85,6 +96,7 @@ async def remove_detached_devices(self) -> None:
# For each detached tunnel, cancel its task, log the removal, and remove it from the active tunnels
for k in diff:
self.active_tunnels[k].task.cancel()
self.active_tunnels[k].rsd.close()
logger.info(f'Removing tunnel {self.active_tunnels[k].address}')
self.active_tunnels.pop(k)

Expand All @@ -105,6 +117,7 @@ def get_interface_index(self, address: str) -> int:
if address_segments != v.split(':')[:-1]:
continue
return k
raise InterfaceIndexNotFoundError(address=address)

async def discover_new_devices(self) -> None:
""" Continuously scans for devices advertising 'RSD' through IPv6 adapters """
Expand All @@ -120,7 +133,11 @@ async def discover_new_devices(self) -> None:
continue
# Extract device details
addr = info.parsed_addresses(IPVersion.V6Only)[0]
interface_index = self.get_interface_index(addr)
try:
interface_index = self.get_interface_index(addr)
except InterfaceIndexNotFoundError as e:
logger.warning(f'Failed to find interface index for {e.address}')
continue
if interface_index in self.active_tunnels:
continue
# Connect to the discovered device
Expand Down Expand Up @@ -164,6 +181,17 @@ async def list_tunnels() -> Dict[str, Tuple[str, int]]:
tunnels[v.rsd.udid] = v.address
return tunnels

@self._app.get('/shutdown')
async def shutdown() -> fastapi.Response:
""" Shutdown Tunneld """
os.kill(os.getpid(), signal.SIGINT)
return fastapi.Response(status_code=200, content='Server shutting down...')

@self._app.get('/clear_tunnels')
async def clear_tunnels() -> fastapi.Response:
self._tunneld_core.clear()
return fastapi.Response(status_code=200, content='Cleared tunnels...')

@self._app.on_event('startup')
async def on_startup() -> None:
""" start TunneldCore """
Expand All @@ -172,6 +200,7 @@ async def on_startup() -> None:

@self._app.on_event('shutdown')
async def on_close() -> None:
logger.info('Closing tunneld tasks...')
await self._tunneld_core.close()

def _run_app(self) -> None:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "pymobiledevice3"
version = "2.24.1"
version = "2.26.1"
description = "Pure python3 implementation for working with iDevices (iPhone, etc...)"
readme = "README.md"
requires-python = ">=3.8"
Expand Down

0 comments on commit fc29a50

Please sign in to comment.