Skip to content

fix: add an option for connecting to different tunnel server port #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
4 changes: 2 additions & 2 deletions tidevice3/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@

DEFAULT_TIMEOUT = 60

def connect_service_provider(udid: Optional[str], force_usbmux: bool = False, usbmux_address: Optional[str] = None) -> LockdownServiceProvider:
def connect_service_provider(udid: Optional[str], force_usbmux: bool = False, usbmux_address: Optional[str] = None, tunneld_port: Optional[int] = 5555) -> LockdownServiceProvider:
"""Connect to device and return LockdownServiceProvider"""
lockdown = create_using_usbmux(serial=udid, usbmux_address=usbmux_address)
if force_usbmux:
return lockdown
if lockdown.product_version >= "17":
return connect_remote_service_discovery_service(lockdown.udid)
return connect_remote_service_discovery_service(lockdown.udid, "http://localhost:%d" % (tunneld_port))

Check warning on line 86 in tidevice3/api.py

View check run for this annotation

Codecov / codecov/patch

tidevice3/api.py#L86

Added line #L86 was not covered by tests
return lockdown


Expand Down
62 changes: 60 additions & 2 deletions tidevice3/cli/cli_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from __future__ import annotations

import collections
import logging;
from functools import update_wrapper

import click
Expand All @@ -14,6 +15,9 @@
from tidevice3.api import connect_service_provider


logger = logging.getLogger(__name__);


class OrderedGroup(click.Group):
def __init__(self, name=None, commands=None, *args, **attrs):
super(OrderedGroup, self).__init__(name, commands, *args, **attrs)
Expand All @@ -24,14 +28,67 @@
return self.commands


class DeprecatedOption(click.Option): # https://stackoverflow.com/a/50402799/12857692
def __init__(self, *args, **kwargs):
self.deprecated = kwargs.pop("deprecated", False);
self.preferred = kwargs.pop("preferred", None);
super(DeprecatedOption, self).__init__(*args, **kwargs);
# end __init__()
# end class


class CommandWithDeprecatedOptions(click.Command):
def make_parser(self, ctx): # Hook 'make_parser()' and during processing check the name used to invoke the option to see if it is preferred
parser = super().make_parser(ctx);

# get the parser options
options = set(parser._short_opt.values());
options |= set(parser._long_opt.values());
for option in options:
if not isinstance(option.obj, DeprecatedOption):
continue;
# end if

def make_process(an_option): # construct a closure to the parser option processor
orig_process = an_option.process;
opt_deprecated = getattr(an_option.obj, "deprecated", None);
assert opt_deprecated is not None, "Expected `deprecated` value for `{}`".format(an_option.obj.name);
opt_preferred = getattr(an_option.obj, "preferred", None);
opt_name = getattr(an_option.obj, "name", None);

def process(value, state): # only called if the option is set
if opt_deprecated:
vv = ["--"+opt_name];
msg = "The '%s' option is deprecated";

Check warning on line 62 in tidevice3/cli/cli_common.py

View check run for this annotation

Codecov / codecov/patch

tidevice3/cli/cli_common.py#L61-L62

Added lines #L61 - L62 were not covered by tests
if opt_preferred is not None:
msg = msg+", use '%s' instead";
vv.append(opt_preferred);

Check warning on line 65 in tidevice3/cli/cli_common.py

View check run for this annotation

Codecov / codecov/patch

tidevice3/cli/cli_common.py#L64-L65

Added lines #L64 - L65 were not covered by tests
# end if
logger.warning(msg % tuple(vv));

Check warning on line 67 in tidevice3/cli/cli_common.py

View check run for this annotation

Codecov / codecov/patch

tidevice3/cli/cli_common.py#L67

Added line #L67 was not covered by tests
# end if
return orig_process(value, state);

Check warning on line 69 in tidevice3/cli/cli_common.py

View check run for this annotation

Codecov / codecov/patch

tidevice3/cli/cli_common.py#L69

Added line #L69 was not covered by tests
# end process()

return process;
# end make_process()

option.process = make_process(option);
# end for
return parser;
# end make_parser()
# end class


@click.group(cls=OrderedGroup, context_settings=dict(help_option_names=["-h", "--help"]))
@click.option("-u", "--udid", default=None, help="udid of device")
@click.option("tunneld_port", "--tunneld-port", default=5555, help="tunneld listen port")
@click.option("usbmux_address", "--usbmux", help=USBMUX_OPTION_HELP)
@click.pass_context
def cli(ctx: click.Context, udid: str, usbmux_address: str):
def cli(ctx: click.Context, udid: str, usbmux_address: str, tunneld_port: int):
ctx.ensure_object(dict)
ctx.obj['udid'] = udid
ctx.obj['usbmux_address'] = usbmux_address
ctx.obj["tunneld_port"] = tunneld_port;


def pass_service_provider(func):
Expand All @@ -50,7 +107,8 @@
def new_func(ctx, *args, **kwargs):
udid = ctx.obj['udid']
usbmux_address = ctx.obj['usbmux_address']
service_provider = connect_service_provider(udid=udid, usbmux_address=usbmux_address)
tunneld_port = ctx.obj["tunneld_port"];
service_provider = connect_service_provider(udid=udid, usbmux_address=usbmux_address, tunneld_port=tunneld_port)

Check warning on line 111 in tidevice3/cli/cli_common.py

View check run for this annotation

Codecov / codecov/patch

tidevice3/cli/cli_common.py#L110-L111

Added lines #L110 - L111 were not covered by tests
with service_provider:
return ctx.invoke(func, service_provider, *args, **kwargs)
return update_wrapper(new_func, func)
Expand Down
12 changes: 7 additions & 5 deletions tidevice3/cli/tunneld.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from pymobiledevice3.exceptions import MuxException
from pymobiledevice3.osu.os_utils import OsUtils

from tidevice3.cli.cli_common import cli
from tidevice3.cli.cli_common import cli, CommandWithDeprecatedOptions, DeprecatedOption;
from tidevice3.cli.list import list_devices
from tidevice3.utils.common import threadsafe_function

Expand Down Expand Up @@ -161,15 +161,16 @@
time.sleep(1)


@cli.command(context_settings={"show_default": True})
@cli.command(context_settings={"show_default": True}, cls=CommandWithDeprecatedOptions)
@click.option(
"--pmd3-path",
"pmd3_path",
help="pymobiledevice3 cli path",
default=None,
)
@click.option("--port", "port", help="listen port", default=5555)
def tunneld(pmd3_path: str, port: int):
@click.option("--port", "port", help="listen port", default=5555, cls=DeprecatedOption, deprecated=True, preferred="--tunneld-port")
@click.pass_context
def tunneld(ctx: click.Context, pmd3_path: str, port: int):
"""start server for iOS >= 17 auto start-tunnel, function like pymobiledevice3 remote tunneld"""
if not os_utils.is_admin:
logger.error("Please run as root(Mac) or administrator(Windows)")
Expand Down Expand Up @@ -197,7 +198,8 @@
target=manager.run_forever, daemon=True, name="device_manager"
).start()
try:
uvicorn.run(app, host="0.0.0.0", port=port)
tunneld_port = ctx.obj["tunneld_port"];
uvicorn.run(app, host="0.0.0.0", port=(tunneld_port if tunneld_port!=5555 else port))

Check warning on line 202 in tidevice3/cli/tunneld.py

View check run for this annotation

Codecov / codecov/patch

tidevice3/cli/tunneld.py#L201-L202

Added lines #L201 - L202 were not covered by tests
finally:
logger.info("Shutting down...")
manager.shutdown()
Loading