To simplify setup, you can run the accompanying script:
    ./setup.sh

This script will:
    * Check for XCode
    * Install a local collection of dependencies, including python and libimobiledevice
    * Create a python virtual env
    * Install all python dependencies
    * Initialize default "config.json" files for ./server and ./provider
    * Copy config files from a previous version to the current version.

Prerequisites for the current installer:
    * Have a recent version of XCode 16 (XCode 14 and 15 are supported, but require a separate build. CFAgent is launched with xcodebuild).
    * Have an iPhone running iOS 13 or greater (iOS 11 and 12 have support, but require a separate build)
    * Phone must be attached via USB, and trust this computer
    * For iOS 16+, the phone must have development mode enabled
    * You should have already deployed a project (any project) from XCode to this phone, from this computer.
      (manual certificate management is possible, see online docs for details)
    * For iOS 17+ your device MUST have an active public internet connection. Apps deployed
      from XCode (including CFAgent) must have their signatures verified against Apple's servers before
      being allowed to launch.

Once all components above are set up, there are three steps left:
    1. resign all apps in ./apps with your own credentials
    2. launch cfserver
    3. register and launch cfprovider

======  App Resigning ======
To sign apps, you will need to have a valid signing identity and mobileprovisioning profile for your device.
You can get suggestions for both by running:
 
    ./apps/Utils/sign_all.macos.sh

If you have only only one .mobileprovision file and one signing identity available, these will be detected
automatically, and you can directly run:

    ./apps/Utils/sign_all.macos.sh ./apps/*.app

Otherwise, output will look something like:
    # Set 'CFA_SIGNING_IDENTITY' to a valid signing identity and run again
    # Available code signing identities:
    # 1) 9CABA8B8B7B6B5B4B3B "Apple Development: [Your Name] (YOURIDENTIFIER)"
    # ...
    # Set 'CFA_PROVISIONING_PROFILE' to a valid .mobileprovision file and run again.
    # You currently have these profiles available:
    # "/path/to/MobileDevice/Provisioning Profiles/xxyyzz.mobileprovision"

Once you have these values, you can use them by running::

    export CFA_SIGNING_IDENTITY=9CABA8B8B7B6B5B4B3B
    export CFA_PROVISIONING_PROFILE="/path/to/MobileDevice/Provisioning Profiles/xxyyzz.mobileprovision"
    ./apps/Utils/sign_all.macos.sh ./apps/*.app

Successful output should end with:
# ...
# === Signing ./apps/vidstream.app ===
# PlugIns/CF Vidstream Extension.appex: replacing existing signature
# ./apps/vidstream.app: replacing existing signature

Note: you might wish to make a script of the commands above, as apps must be resigned after
every ControlFloor software update.

====== Launch ControlFloor Server ======
ControlFloor server is located in the "server" subdirectory of this installation.

There is a config file "config.json" where you can toggle various options.
It currently contains plaintext passwords that you will need to log into the
ControlFloor web interface.  The setup script will initialize these passwords
to random values.
(User management features will be added in a future release).

Note the defaults in config.json:
#    listen: ":8080"
#    https: true

With the default 8080 configuration, you do not need to be root to run the application.
If you choose to use port 443 (the default https port), cfserver will need to be
launched with sudo.  Otherwise, to start the server, run:

    ./cfserver run

You can now connect to the server in a web browser at:
    https://localhost:8080

====== Launch ControlFloor Provider ======
ControlFloor's iOS provider is located in the ./provider directory of this project.

It also contains a "config.json" file.  Note the options beginning:
# controlfloor: {
#        host: "localhost:8080"

If you changed the default port for cfserver, be sure to change the address here as well.

If you have a license key, you can enter it in the licenseKeys[] section now.

There is a one-time setup needed before connecting devices:

    ./cfprovider register  # Hit [enter] twice when prompted

Once this is complete, you can either run:

    ./cfprovider run --udid [udid]

or to automatically connect/reconnect to all attached devices:

    ./cfprovider runner

You might wish to start with one device first option to make sure your confuration is correct.  You
can list your attached devices with the command:

    idevice_id

or for more verbose output, including devices models and names:

     ./venv/bin/pymobiledevice3 usbmux list

The first time you connect to a device, it may take a minute or more to connect.
For iOS17 devices, you may see an additional "trust" prompt on the device screen.
Tap "trust".  cfprovider may exit and need to be started after this is complete.

Next cfprovider will:
    * detect and install any missing support apps from the ./apps folder (CFAgent, CFAUInspector,
      and Vidstream)
    * launch CFAgent (using go-ios for iOS 16 and lower, and xcodebuild for iOS 17+)
    * create a special tunnel using Remote Service Discovery (RSD) needed for various operations,
      (such as killing and starting processes) an iOS 17.
    * connect to ControlFloor server

Once you've connected successfully, you should be able to see your device in
ControlFloor from your browser.  If you have not configured a license key,
you can still see video and access a more functional demo mode by clicking:

    "Launch Mobile Notes (Demo Mode)"

====== Troubleshooting commands ======
In the commands below, substitute [UDID] with the actual udid of your device (see: idevice_id).  

If a device failes to connect, it is usually possible to identify where the failure occured. Usual causes are:
   * Device not trusted
   * Developer mode not enabled
   * Device has no wifi connection and can't launch software
   * apps not signed correctly (apps will fail to install, or will install and fail to launch)
     This may occur with a valid mobileprovision file that does not include a particular device
   * Envrionment setup issues, such as missing python3, missing dependencies, helper apps not
     set suid, not launching RSD tunnels (ios17+) with root permission, etc.

* Uninstall all CFA apps from all devices(useful if signing certs have changed):
    ./provider/bin/uninstallall

* Ensure apps are installed:
    ideviceinstaller  -l -u [UDID]

Output Example:
# CFBundleIdentifier, CFBundleVersion, CFBundleDisplayName
# com.dryark.CFAgent.xctrunner, "0.41.0+Xcode15.3-15E204a", "CFAgent-Runner"
# com.dryark.CFAUIInspector, "0.41.0+Xcode15.3-15E204a", "CFAUIInspector"
# com.dryark.vidstream, "0.41.0+Xcode15.3-15E204a", "CF Vidstream"

* Launch rsd tunnel manually for device with ios_rsd_tunnel (default):

    CFTOOLS=./provider/bin PYTHONPATH=./provider/python ./venv/bin/python3 -u -m ios_rsd_tunnel   remote-tunnel --udid [UDID]

Output Example:
#{ "ipv6": "fdcd:2a4f:467f::1", "port": 64551 }

* Launch rsd tunnel manually for device with pymobiledevice3 (-rsdMethod pmd3, sudo required):

    PYTHONPATH=./provider/python sudo ./venv/bin/python3 -u -m pymobiledevice3 remote start-tunnel --udid [UDID] --script-mode

Output Example:
# 2024-05-08 19:10:15 hostname.local pymobiledevice3.cli.remote[63806] INFO tunnel created
# fdab:f042:ca9a::1 64554

* Launch CFAgent with xcode (iOS17 +):
    cd ./provider
    /usr/bin/xcodebuild test-without-building -xctestrun ./cfagent.xctestrun -destination platform=iOS,id=[UDID]

Output for should reach:
# ...
# 2024-05-08 19:13:21.999093+0900 CFAgent-Runner[1841:1310391] listenfd: 11
# 2024-05-08 19:13:21.999546+0900 CFAgent-Runner[1841:1310391] CFAgent: Ready on port 8101.

* Launch CFAgent with go-ios (<= iOS16): 
    cd ./provider
   ./bin/go-ios runwda --bundleid com.dryark.CFAgent.xctrunner --testrunnerbundleid com.dryark.CFAgent.xctrunner --xctestconfig CFAgent.xctest --udid [UDID]

Output for either should reach:
# ...
# {"level":"info","msg":"2024-05-08 19:22:38.514 CFAgent-Runner[664:700046] listenfd: 9\n","time":"2024-05-08T19:22:38+09:00"}
# {"level":"info","msg":"2024-05-08 19:22:38.515 CFAgent-Runner[664:700046] CFAgent: Ready on port 8101.\n","time":"2024-05-08T19:22:38+09:00"}
