Repository navigation
Conversation
AltStore Classic 2.3's "Set up Remote AltServer" sends PairingFileRequest, which AltServer-Linux rejected. upstream_repo now handles the request (PairingFileRequest handler in AltServer-Windows ng-fixes); this commit adds the Linux implementation and the idevice build. src/DevicePairingManager.cpp ports DevicePairingManager.swift from AltServer for macOS: it finds the device's usbmuxd device_id by UDID, builds a usbmuxd provider, pairs with tunnel_pair_usb() (the device shows a Trust prompt) and serializes the RPPairing file. Both usbmuxd connections honor USBMUXD_SOCKET_ADDRESS, like the rest of AltServer-Linux. The pairing runs on a thread with an 8 MiB stack because polling idevice's pairing future overflowed the 128 KiB default stack of musl threads (SIGSEGV in tunnel_pair_usb on a cpprestsdk pool thread). libraries/idevice is jkcoxson/idevice v0.1.68 with the features usbmuxd,tunnel_tcp_stack,ring. Its static library also defines libplist-compatible plist_* functions and the Rust standard library, which clash with the vendored libplist, so makefiles/idevice-build/idevice.mak prelinks it with ld -r and keeps only the functions in idevice-api.txt global. IDEVICE_FFI_LIB selects a prebuilt library; without it the Makefile runs cargo. The builder images have no Rust toolchain, so CI cross-compiles the library for each architecture with cargo-zigbuild (build-idevice-cross.sh) and passes it in. Tested with AltStore Classic 2.3 on an iPhone 16 Pro running iOS 26.6.2: Remote AltServer setup received the pairing file, and with Prefer Remote AltServer on and AltServer stopped, AltStore installed an app on-device. x86_64, i586, armv7 and aarch64 build and link statically; the armv7 and aarch64 binaries were started under QEMU user emulation and found the device through usbmuxd. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DevicePairingManager left USBMUXD_SOCKET_ADDRESS to idevice, which reads every value containing ':' as a numeric TCP address. So the libusbmuxd form UNIX:<path>, the one deploy/altserver-stack.yml sets, failed with FfiInvalidArg and AltStore got a generic "couldn't be configured" error, although the rest of AltServer accepts that value. The address is now read once by libusbmuxd's rules (UNIX:<path>, <host>:<port> or [<host>]:<port>, otherwise /var/run/usbmuxd), and the device lookup and the pairing provider both connect to it. usbmuxd can list one UDID twice, over USB and over the network. The lookup took the first match, so a network entry could be paired over. It now accepts only an entry whose connection type is USB, which is what the DeviceNotFound message already says. The usbmuxd connection used for the device list is closed as soon as the device_id is known, instead of staying open until the user answers the Trust prompt. idevice-api.txt exports the three functions this needs and drops the two it no longer calls. Tested with a temporary instance and a PairingFileRequest for a UDID that is not connected: DeviceNotFound with UNIX:<socket> relayed to netmuxd and with 127.0.0.1:27015. The build before this change answered the UNIX: case with "idevice error 33: FfiInvalidArg". The phone's UDID, listed by netmuxd only as Network, also gets DeviceNotFound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the way The cargo rule had no prerequisites, so after the first build make never ran cargo again: a submodule bump or a change to idevice-features.txt was prelinked from the old library. cargo now runs on every make. When nothing changed it leaves libidevice_ffi.a untouched, so make does not prelink again. idevice.mak sets .DELETE_ON_ERROR like the other makefiles, so a failed ld or objcopy does not leave a partial idevice_ffi.o that the next make treats as built. build-idevice-cross.sh builds into libraries/idevice/target/cross instead of target-cross. idevice's .gitignore covers target/, so the submodule no longer shows untracked content after a cross build. Tested in rust:latest with plain make: an unchanged tree and a touched idevice-features.txt run cargo in about 0.1 s and leave idevice_ffi.o alone; adding a feature rebuilds the crate and prelinks again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tunnel_pair_usb() returns only when the user answers the Trust prompt, the device disconnects or the connection fails, and idevice has no call that cancels it. So each retry while the prompt was still up started another pairing with the same device and blocked one more request thread and 8 MiB pairing stack. A request for a UDID that is already pairing now fails at once with "AltServer is already pairing with this device." The first pairing still waits for the user, as the macOS version does. Tested with a fake usbmuxd that lists the UDID as Network and then USB and never answers the pairing's Connect: the pairing connects with the USB entry's DeviceID, a second request fails in 0.03 s, and after the fake drops the connection a new request is accepted. Without this change the second request got no reply within 60 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks for this, and sorry for the slow reply. The pairing support is useful, and the write-up made it easy to follow. The
Could you rebase this onto the current If you don't have time for that, just tell me, and I will do the rebase myself and keep you as the author. |
|
hey @jaakkopalvaila, thanks for having a look. yeah, under a bit of a crunch lately. if you have the time to rebase it, would be grateful. (based from my experience, Claude can probably transfer all useful work on this branch to the new base with little intervention. Then it was mostly running rounds of reviews until it saturated.) |
AltStore Classic 2.3's Set up Remote AltServer… sends AltServer a
PairingFileRequest. AltServer-Linux rejected it ("AltServer does not support this request"), so AltStore showed "unable to pair". This PR implements it, following AltServer for macOS.Depends on jaakkopalvaila/AltServer-Windows#1, which adds the request handler to
ClientConnectionand theDevicePairingManagerinterface. Theupstream_reposubmodule here points at that PR's commit (b0d2846). If that PR is squashed or rebased on merge, this pointer needs updating to the merged commit.What it does
src/DevicePairingManager.cppis a port ofDevicePairingManager.swift:device_idby UDIDtunnel_pair_usb(); the device shows a Trust prompt for "AltServer on "USBMUXD_SOCKET_ADDRESSonce, by libusbmuxd's rules (UNIX:<path>,<host>:<port>,[<host>]:<port>, otherwise/var/run/usbmuxd), and uses that address for both the device lookup and the pairing, so netmuxd setups keep both on the same muxer. idevice's own reader rejects theUNIX:form.tunnel_pair_usb()can't be cancelled, so there is no timeout.tunnel_pair_usb, withrspabout 130 KiB below the thread's stack top.libraries/ideviceis jkcoxson/idevice v0.1.68, built withusbmuxd,tunnel_tcp_stack,ring.plist_*functions, plus the Rust standard library. Both clash with the vendored libplist.makefiles/idevice-build/idevice.makprelinks it withld -rand keeps only the 18 functions inidevice-api.txtglobal (objcopy --keep-global-symbols).plist_new_dict, libplist's, and no unresolved symbols.IDEVICE_FFI_LIBpoints make at a prebuilt library. Without it, the Makefile runs cargo on every make and lets cargo decide whether anything changed.idevice.maksets.DELETE_ON_ERROR.libraries/idevice/target/cross, which idevice's.gitignorecovers.build-idevice-cross.sh, image pinned to0.23.4), one Rust target per matrix entry.Testing
PairingFileRequestfor a UDID that isn't connected returnsDeviceNotFoundwith the macOS failure reason and recovery suggestion, forUSBMUXD_SOCKET_ADDRESSset to127.0.0.1:27015and toUNIX:<socket>.🤖 Generated with Claude Code